From b5a3c0d8618e7e8bbe68df33d72f60e1e7456d88 Mon Sep 17 00:00:00 2001 From: Edwin Date: Fri, 23 Jun 2017 11:37:04 +0800 Subject: [PATCH] add vendors --- vendor/github.com/btcsuite/btcd/LICENSE | 16 + .../github.com/btcsuite/btcd/btcec/README.md | 68 + .../github.com/btcsuite/btcd/btcec/btcec.go | 956 ++++ .../btcsuite/btcd/btcec/ciphering.go | 216 + vendor/github.com/btcsuite/btcd/btcec/doc.go | 21 + .../github.com/btcsuite/btcd/btcec/field.go | 1223 +++++ .../btcsuite/btcd/btcec/gensecp256k1.go | 203 + .../btcsuite/btcd/btcec/precompute.go | 67 + .../github.com/btcsuite/btcd/btcec/privkey.go | 73 + .../github.com/btcsuite/btcd/btcec/pubkey.go | 172 + .../btcsuite/btcd/btcec/secp256k1.go | 10 + .../btcsuite/btcd/btcec/signature.go | 539 ++ .../github.com/ethereum/go-ethereum/COPYING | 619 +++ .../ethereum/go-ethereum/COPYING.LESSER | 165 + .../ethereum/go-ethereum/common/big.go | 30 + .../ethereum/go-ethereum/common/bytes.go | 111 + .../ethereum/go-ethereum/common/debug.go | 52 + .../ethereum/go-ethereum/common/format.go | 40 + .../go-ethereum/common/hexutil/hexutil.go | 236 + .../go-ethereum/common/hexutil/json.go | 297 ++ .../ethereum/go-ethereum/common/math/big.go | 212 + .../go-ethereum/common/math/integer.go | 99 + .../ethereum/go-ethereum/common/path.go | 47 + .../ethereum/go-ethereum/common/size.go | 37 + .../ethereum/go-ethereum/common/test_utils.go | 53 + .../ethereum/go-ethereum/common/types.go | 208 + .../go-ethereum/common/types_template.go | 64 + .../ethereum/go-ethereum/crypto/crypto.go | 190 + .../go-ethereum/crypto/secp256k1/curve.go | 312 ++ .../go-ethereum/crypto/secp256k1/ext.h | 87 + .../crypto/secp256k1/libsecp256k1/.gitignore | 49 + .../crypto/secp256k1/libsecp256k1/.travis.yml | 69 + .../crypto/secp256k1/libsecp256k1/COPYING | 19 + .../crypto/secp256k1/libsecp256k1/Makefile.am | 177 + .../crypto/secp256k1/libsecp256k1/README.md | 61 + .../crypto/secp256k1/libsecp256k1/TODO | 3 + .../crypto/secp256k1/libsecp256k1/autogen.sh | 3 + .../build-aux/m4/ax_jni_include_dir.m4 | 140 + .../build-aux/m4/ax_prog_cc_for_build.m4 | 125 + .../libsecp256k1/build-aux/m4/bitcoin_secp.m4 | 69 + .../secp256k1/libsecp256k1/configure.ac | 493 ++ .../libsecp256k1/contrib/lax_der_parsing.c | 150 + .../libsecp256k1/contrib/lax_der_parsing.h | 91 + .../contrib/lax_der_privatekey_parsing.c | 113 + .../contrib/lax_der_privatekey_parsing.h | 90 + .../libsecp256k1/include/secp256k1.h | 577 +++ .../libsecp256k1/include/secp256k1_ecdh.h | 31 + .../libsecp256k1/include/secp256k1_recovery.h | 110 + .../secp256k1/libsecp256k1/libsecp256k1.pc.in | 13 + .../secp256k1/libsecp256k1/obj/.gitignore | 0 .../libsecp256k1/sage/group_prover.sage | 322 ++ .../libsecp256k1/sage/secp256k1.sage | 306 ++ .../libsecp256k1/sage/weierstrass_prover.sage | 264 + .../libsecp256k1/src/asm/field_10x26_arm.s | 919 ++++ .../secp256k1/libsecp256k1/src/basic-config.h | 32 + .../crypto/secp256k1/libsecp256k1/src/bench.h | 66 + .../secp256k1/libsecp256k1/src/bench_ecdh.c | 54 + .../libsecp256k1/src/bench_internal.c | 382 ++ .../libsecp256k1/src/bench_recover.c | 60 + .../libsecp256k1/src/bench_schnorr_verify.c | 73 + .../secp256k1/libsecp256k1/src/bench_sign.c | 56 + .../secp256k1/libsecp256k1/src/bench_verify.c | 112 + .../crypto/secp256k1/libsecp256k1/src/ecdsa.h | 21 + .../secp256k1/libsecp256k1/src/ecdsa_impl.h | 315 ++ .../crypto/secp256k1/libsecp256k1/src/eckey.h | 25 + .../secp256k1/libsecp256k1/src/eckey_impl.h | 99 + .../secp256k1/libsecp256k1/src/ecmult.h | 31 + .../secp256k1/libsecp256k1/src/ecmult_const.h | 15 + .../libsecp256k1/src/ecmult_const_impl.h | 239 + .../secp256k1/libsecp256k1/src/ecmult_gen.h | 43 + .../libsecp256k1/src/ecmult_gen_impl.h | 210 + .../secp256k1/libsecp256k1/src/ecmult_impl.h | 406 ++ .../crypto/secp256k1/libsecp256k1/src/field.h | 132 + .../secp256k1/libsecp256k1/src/field_10x26.h | 47 + .../libsecp256k1/src/field_10x26_impl.h | 1140 +++++ .../secp256k1/libsecp256k1/src/field_5x52.h | 47 + .../libsecp256k1/src/field_5x52_asm_impl.h | 502 ++ .../libsecp256k1/src/field_5x52_impl.h | 451 ++ .../libsecp256k1/src/field_5x52_int128_impl.h | 277 + .../secp256k1/libsecp256k1/src/field_impl.h | 315 ++ .../secp256k1/libsecp256k1/src/gen_context.c | 74 + .../crypto/secp256k1/libsecp256k1/src/group.h | 144 + .../secp256k1/libsecp256k1/src/group_impl.h | 700 +++ .../crypto/secp256k1/libsecp256k1/src/hash.h | 41 + .../secp256k1/libsecp256k1/src/hash_impl.h | 281 + .../src/java/org/bitcoin/NativeSecp256k1.java | 446 ++ .../java/org/bitcoin/NativeSecp256k1Test.java | 226 + .../java/org/bitcoin/NativeSecp256k1Util.java | 45 + .../java/org/bitcoin/Secp256k1Context.java | 51 + .../src/java/org_bitcoin_NativeSecp256k1.c | 377 ++ .../src/java/org_bitcoin_NativeSecp256k1.h | 119 + .../src/java/org_bitcoin_Secp256k1Context.c | 15 + .../src/java/org_bitcoin_Secp256k1Context.h | 22 + .../src/modules/ecdh/Makefile.am.include | 8 + .../libsecp256k1/src/modules/ecdh/main_impl.h | 54 + .../src/modules/ecdh/tests_impl.h | 105 + .../src/modules/recovery/Makefile.am.include | 8 + .../src/modules/recovery/main_impl.h | 193 + .../src/modules/recovery/tests_impl.h | 393 ++ .../crypto/secp256k1/libsecp256k1/src/num.h | 74 + .../secp256k1/libsecp256k1/src/num_gmp.h | 20 + .../secp256k1/libsecp256k1/src/num_gmp_impl.h | 288 ++ .../secp256k1/libsecp256k1/src/num_impl.h | 24 + .../secp256k1/libsecp256k1/src/scalar.h | 106 + .../secp256k1/libsecp256k1/src/scalar_4x64.h | 19 + .../libsecp256k1/src/scalar_4x64_impl.h | 949 ++++ .../secp256k1/libsecp256k1/src/scalar_8x32.h | 19 + .../libsecp256k1/src/scalar_8x32_impl.h | 721 +++ .../secp256k1/libsecp256k1/src/scalar_impl.h | 370 ++ .../secp256k1/libsecp256k1/src/scalar_low.h | 15 + .../libsecp256k1/src/scalar_low_impl.h | 114 + .../secp256k1/libsecp256k1/src/secp256k1.c | 561 ++ .../secp256k1/libsecp256k1/src/testrand.h | 38 + .../libsecp256k1/src/testrand_impl.h | 110 + .../crypto/secp256k1/libsecp256k1/src/tests.c | 4525 +++++++++++++++++ .../libsecp256k1/src/tests_exhaustive.c | 470 ++ .../crypto/secp256k1/libsecp256k1/src/util.h | 113 + .../go-ethereum/crypto/secp256k1/panic_cb.go | 33 + .../go-ethereum/crypto/secp256k1/secp256.go | 130 + .../ethereum/go-ethereum/crypto/sha3/LICENSE | 27 + .../ethereum/go-ethereum/crypto/sha3/PATENTS | 22 + .../ethereum/go-ethereum/crypto/sha3/doc.go | 66 + .../go-ethereum/crypto/sha3/hashes.go | 71 + .../go-ethereum/crypto/sha3/keccakf.go | 412 ++ .../go-ethereum/crypto/sha3/keccakf_amd64.go | 13 + .../go-ethereum/crypto/sha3/keccakf_amd64.s | 390 ++ .../go-ethereum/crypto/sha3/register.go | 18 + .../ethereum/go-ethereum/crypto/sha3/sha3.go | 193 + .../ethereum/go-ethereum/crypto/sha3/shake.go | 60 + .../ethereum/go-ethereum/crypto/sha3/xor.go | 16 + .../go-ethereum/crypto/sha3/xor_generic.go | 28 + .../go-ethereum/crypto/sha3/xor_unaligned.go | 58 + .../go-ethereum/crypto/signature_cgo.go | 64 + .../go-ethereum/crypto/signature_nocgo.go | 77 + .../ethereum/go-ethereum/log/CONTRIBUTORS | 11 + .../ethereum/go-ethereum/log/LICENSE | 13 + .../ethereum/go-ethereum/log/README.md | 77 + .../go-ethereum/log/README_ETHEREUM.md | 5 + .../ethereum/go-ethereum/log/doc.go | 333 ++ .../ethereum/go-ethereum/log/format.go | 363 ++ .../ethereum/go-ethereum/log/handler.go | 361 ++ .../ethereum/go-ethereum/log/handler_glog.go | 227 + .../ethereum/go-ethereum/log/handler_go13.go | 26 + .../ethereum/go-ethereum/log/handler_go14.go | 23 + .../ethereum/go-ethereum/log/logger.go | 240 + .../ethereum/go-ethereum/log/root.go | 61 + .../ethereum/go-ethereum/log/syslog.go | 57 + .../ethereum/go-ethereum/params/bootnodes.go | 60 + .../ethereum/go-ethereum/params/config.go | 318 ++ .../ethereum/go-ethereum/params/dao.go | 167 + .../go-ethereum/params/denomination.go | 34 + .../ethereum/go-ethereum/params/gas_table.go | 77 + .../go-ethereum/params/protocol_params.go | 75 + .../ethereum/go-ethereum/params/util.go | 47 + .../ethereum/go-ethereum/params/version.go | 45 + .../ethereum/go-ethereum/rlp/decode.go | 1041 ++++ .../ethereum/go-ethereum/rlp/doc.go | 33 + .../ethereum/go-ethereum/rlp/encode.go | 652 +++ .../ethereum/go-ethereum/rlp/raw.go | 156 + .../ethereum/go-ethereum/rlp/typecache.go | 156 + .../ethereum/go-ethereum/trie/encoding.go | 114 + .../ethereum/go-ethereum/trie/errors.go | 46 + .../ethereum/go-ethereum/trie/hasher.go | 173 + .../ethereum/go-ethereum/trie/iterator.go | 499 ++ .../ethereum/go-ethereum/trie/node.go | 224 + .../ethereum/go-ethereum/trie/proof.go | 148 + .../ethereum/go-ethereum/trie/secure_trie.go | 213 + .../ethereum/go-ethereum/trie/sync.go | 285 ++ .../ethereum/go-ethereum/trie/trie.go | 510 ++ vendor/github.com/getamis/go-ethereum/COPYING | 619 +++ .../getamis/go-ethereum/COPYING.LESSER | 165 + .../getamis/go-ethereum/common/big.go | 30 + .../getamis/go-ethereum/common/bytes.go | 111 + .../getamis/go-ethereum/common/debug.go | 52 + .../getamis/go-ethereum/common/format.go | 40 + .../go-ethereum/common/hexutil/hexutil.go | 236 + .../go-ethereum/common/hexutil/json.go | 297 ++ .../getamis/go-ethereum/common/path.go | 47 + .../getamis/go-ethereum/common/size.go | 37 + .../getamis/go-ethereum/common/test_utils.go | 53 + .../getamis/go-ethereum/common/types.go | 208 + .../go-ethereum/common/types_template.go | 64 + .../getamis/go-ethereum/core/types/block.go | 455 ++ .../getamis/go-ethereum/core/types/bloom9.go | 130 + .../go-ethereum/core/types/derive_sha.go | 41 + .../go-ethereum/core/types/gen_header_json.go | 136 + .../go-ethereum/core/types/gen_log_json.go | 88 + .../core/types/gen_receipt_json.go | 77 + .../go-ethereum/core/types/gen_tx_json.go | 97 + .../go-ethereum/core/types/istanbul.go | 107 + .../getamis/go-ethereum/core/types/log.go | 137 + .../getamis/go-ethereum/core/types/receipt.go | 137 + .../go-ethereum/core/types/transaction.go | 469 ++ .../core/types/transaction_signing.go | 320 ++ .../getamis/go-ethereum/rlp/decode.go | 1041 ++++ .../github.com/getamis/go-ethereum/rlp/doc.go | 33 + .../getamis/go-ethereum/rlp/encode.go | 652 +++ .../github.com/getamis/go-ethereum/rlp/raw.go | 156 + .../getamis/go-ethereum/rlp/typecache.go | 156 + vendor/github.com/go-stack/stack/LICENSE.md | 21 + vendor/github.com/go-stack/stack/README.md | 38 + vendor/github.com/go-stack/stack/stack.go | 349 ++ .../github.com/naoina/go-stringutil/LICENSE | 19 + .../github.com/naoina/go-stringutil/README.md | 13 + vendor/github.com/naoina/go-stringutil/da.go | 253 + .../naoina/go-stringutil/strings.go | 320 ++ vendor/github.com/naoina/toml/LICENSE | 19 + vendor/github.com/naoina/toml/README.md | 392 ++ vendor/github.com/naoina/toml/ast/ast.go | 192 + vendor/github.com/naoina/toml/config.go | 86 + vendor/github.com/naoina/toml/decode.go | 478 ++ vendor/github.com/naoina/toml/encode.go | 398 ++ vendor/github.com/naoina/toml/error.go | 107 + vendor/github.com/naoina/toml/parse.go | 362 ++ vendor/github.com/naoina/toml/parse.peg | 147 + vendor/github.com/naoina/toml/parse.peg.go | 2579 ++++++++++ vendor/github.com/naoina/toml/util.go | 65 + vendor/github.com/rcrowley/go-metrics/LICENSE | 29 + .../github.com/rcrowley/go-metrics/README.md | 153 + .../github.com/rcrowley/go-metrics/counter.go | 112 + .../github.com/rcrowley/go-metrics/debug.go | 76 + vendor/github.com/rcrowley/go-metrics/ewma.go | 118 + .../github.com/rcrowley/go-metrics/gauge.go | 120 + .../rcrowley/go-metrics/gauge_float64.go | 127 + .../rcrowley/go-metrics/graphite.go | 113 + .../rcrowley/go-metrics/healthcheck.go | 61 + .../rcrowley/go-metrics/histogram.go | 202 + vendor/github.com/rcrowley/go-metrics/json.go | 87 + vendor/github.com/rcrowley/go-metrics/log.go | 80 + .../github.com/rcrowley/go-metrics/memory.md | 285 ++ .../github.com/rcrowley/go-metrics/meter.go | 233 + .../github.com/rcrowley/go-metrics/metrics.go | 13 + .../rcrowley/go-metrics/opentsdb.go | 119 + .../rcrowley/go-metrics/registry.go | 270 + .../github.com/rcrowley/go-metrics/runtime.go | 212 + .../rcrowley/go-metrics/runtime_cgo.go | 10 + .../go-metrics/runtime_gccpufraction.go | 9 + .../rcrowley/go-metrics/runtime_no_cgo.go | 7 + .../go-metrics/runtime_no_gccpufraction.go | 9 + .../github.com/rcrowley/go-metrics/sample.go | 616 +++ .../github.com/rcrowley/go-metrics/syslog.go | 78 + .../github.com/rcrowley/go-metrics/timer.go | 311 ++ .../rcrowley/go-metrics/validate.sh | 10 + .../github.com/rcrowley/go-metrics/writer.go | 100 + vendor/gopkg.in/karalabe/cookiejar.v2/LICENSE | 25 + .../cookiejar.v2/collections/prque/prque.go | 66 + .../cookiejar.v2/collections/prque/sstack.go | 91 + vendor/vendor.json | 303 ++ 248 files changed, 52227 insertions(+) create mode 100644 vendor/github.com/btcsuite/btcd/LICENSE create mode 100644 vendor/github.com/btcsuite/btcd/btcec/README.md create mode 100644 vendor/github.com/btcsuite/btcd/btcec/btcec.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/ciphering.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/doc.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/field.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/gensecp256k1.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/precompute.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/privkey.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/pubkey.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/secp256k1.go create mode 100644 vendor/github.com/btcsuite/btcd/btcec/signature.go create mode 100644 vendor/github.com/ethereum/go-ethereum/COPYING create mode 100644 vendor/github.com/ethereum/go-ethereum/COPYING.LESSER create mode 100644 vendor/github.com/ethereum/go-ethereum/common/big.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/bytes.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/debug.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/format.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/hexutil/hexutil.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/math/big.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/math/integer.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/path.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/size.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/test_utils.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/types.go create mode 100644 vendor/github.com/ethereum/go-ethereum/common/types_template.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/crypto.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/curve.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/ext.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO create mode 100755 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include create mode 100755 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h create mode 100755 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/panic_cb.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/secp256.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/LICENSE create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/PATENTS create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/doc.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/hashes.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/register.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/shake.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_generic.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go create mode 100644 vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/CONTRIBUTORS create mode 100644 vendor/github.com/ethereum/go-ethereum/log/LICENSE create mode 100644 vendor/github.com/ethereum/go-ethereum/log/README.md create mode 100644 vendor/github.com/ethereum/go-ethereum/log/README_ETHEREUM.md create mode 100644 vendor/github.com/ethereum/go-ethereum/log/doc.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/format.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/handler.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/handler_glog.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/handler_go13.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/handler_go14.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/logger.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/root.go create mode 100644 vendor/github.com/ethereum/go-ethereum/log/syslog.go create mode 100644 vendor/github.com/ethereum/go-ethereum/params/bootnodes.go create mode 100644 vendor/github.com/ethereum/go-ethereum/params/config.go create mode 100644 vendor/github.com/ethereum/go-ethereum/params/dao.go create mode 100644 vendor/github.com/ethereum/go-ethereum/params/denomination.go create mode 100644 vendor/github.com/ethereum/go-ethereum/params/gas_table.go create mode 100644 vendor/github.com/ethereum/go-ethereum/params/protocol_params.go create mode 100644 vendor/github.com/ethereum/go-ethereum/params/util.go create mode 100644 vendor/github.com/ethereum/go-ethereum/params/version.go create mode 100644 vendor/github.com/ethereum/go-ethereum/rlp/decode.go create mode 100644 vendor/github.com/ethereum/go-ethereum/rlp/doc.go create mode 100644 vendor/github.com/ethereum/go-ethereum/rlp/encode.go create mode 100644 vendor/github.com/ethereum/go-ethereum/rlp/raw.go create mode 100644 vendor/github.com/ethereum/go-ethereum/rlp/typecache.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/encoding.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/errors.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/hasher.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/iterator.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/node.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/proof.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/sync.go create mode 100644 vendor/github.com/ethereum/go-ethereum/trie/trie.go create mode 100644 vendor/github.com/getamis/go-ethereum/COPYING create mode 100644 vendor/github.com/getamis/go-ethereum/COPYING.LESSER create mode 100644 vendor/github.com/getamis/go-ethereum/common/big.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/bytes.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/debug.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/format.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/hexutil/hexutil.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/hexutil/json.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/path.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/size.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/test_utils.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/types.go create mode 100644 vendor/github.com/getamis/go-ethereum/common/types_template.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/block.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/bloom9.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/derive_sha.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/gen_header_json.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/gen_log_json.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/gen_receipt_json.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/gen_tx_json.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/istanbul.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/log.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/receipt.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/transaction.go create mode 100644 vendor/github.com/getamis/go-ethereum/core/types/transaction_signing.go create mode 100644 vendor/github.com/getamis/go-ethereum/rlp/decode.go create mode 100644 vendor/github.com/getamis/go-ethereum/rlp/doc.go create mode 100644 vendor/github.com/getamis/go-ethereum/rlp/encode.go create mode 100644 vendor/github.com/getamis/go-ethereum/rlp/raw.go create mode 100644 vendor/github.com/getamis/go-ethereum/rlp/typecache.go create mode 100644 vendor/github.com/go-stack/stack/LICENSE.md create mode 100644 vendor/github.com/go-stack/stack/README.md create mode 100644 vendor/github.com/go-stack/stack/stack.go create mode 100644 vendor/github.com/naoina/go-stringutil/LICENSE create mode 100644 vendor/github.com/naoina/go-stringutil/README.md create mode 100644 vendor/github.com/naoina/go-stringutil/da.go create mode 100644 vendor/github.com/naoina/go-stringutil/strings.go create mode 100644 vendor/github.com/naoina/toml/LICENSE create mode 100644 vendor/github.com/naoina/toml/README.md create mode 100644 vendor/github.com/naoina/toml/ast/ast.go create mode 100644 vendor/github.com/naoina/toml/config.go create mode 100644 vendor/github.com/naoina/toml/decode.go create mode 100644 vendor/github.com/naoina/toml/encode.go create mode 100644 vendor/github.com/naoina/toml/error.go create mode 100644 vendor/github.com/naoina/toml/parse.go create mode 100644 vendor/github.com/naoina/toml/parse.peg create mode 100644 vendor/github.com/naoina/toml/parse.peg.go create mode 100644 vendor/github.com/naoina/toml/util.go create mode 100644 vendor/github.com/rcrowley/go-metrics/LICENSE create mode 100644 vendor/github.com/rcrowley/go-metrics/README.md create mode 100644 vendor/github.com/rcrowley/go-metrics/counter.go create mode 100644 vendor/github.com/rcrowley/go-metrics/debug.go create mode 100644 vendor/github.com/rcrowley/go-metrics/ewma.go create mode 100644 vendor/github.com/rcrowley/go-metrics/gauge.go create mode 100644 vendor/github.com/rcrowley/go-metrics/gauge_float64.go create mode 100644 vendor/github.com/rcrowley/go-metrics/graphite.go create mode 100644 vendor/github.com/rcrowley/go-metrics/healthcheck.go create mode 100644 vendor/github.com/rcrowley/go-metrics/histogram.go create mode 100644 vendor/github.com/rcrowley/go-metrics/json.go create mode 100644 vendor/github.com/rcrowley/go-metrics/log.go create mode 100644 vendor/github.com/rcrowley/go-metrics/memory.md create mode 100644 vendor/github.com/rcrowley/go-metrics/meter.go create mode 100644 vendor/github.com/rcrowley/go-metrics/metrics.go create mode 100644 vendor/github.com/rcrowley/go-metrics/opentsdb.go create mode 100644 vendor/github.com/rcrowley/go-metrics/registry.go create mode 100644 vendor/github.com/rcrowley/go-metrics/runtime.go create mode 100644 vendor/github.com/rcrowley/go-metrics/runtime_cgo.go create mode 100644 vendor/github.com/rcrowley/go-metrics/runtime_gccpufraction.go create mode 100644 vendor/github.com/rcrowley/go-metrics/runtime_no_cgo.go create mode 100644 vendor/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go create mode 100644 vendor/github.com/rcrowley/go-metrics/sample.go create mode 100644 vendor/github.com/rcrowley/go-metrics/syslog.go create mode 100644 vendor/github.com/rcrowley/go-metrics/timer.go create mode 100755 vendor/github.com/rcrowley/go-metrics/validate.sh create mode 100644 vendor/github.com/rcrowley/go-metrics/writer.go create mode 100755 vendor/gopkg.in/karalabe/cookiejar.v2/LICENSE create mode 100755 vendor/gopkg.in/karalabe/cookiejar.v2/collections/prque/prque.go create mode 100755 vendor/gopkg.in/karalabe/cookiejar.v2/collections/prque/sstack.go create mode 100644 vendor/vendor.json diff --git a/vendor/github.com/btcsuite/btcd/LICENSE b/vendor/github.com/btcsuite/btcd/LICENSE new file mode 100644 index 00000000..53ba0c56 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/LICENSE @@ -0,0 +1,16 @@ +ISC License + +Copyright (c) 2013-2017 The btcsuite developers +Copyright (c) 2015-2016 The Decred developers + +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/vendor/github.com/btcsuite/btcd/btcec/README.md b/vendor/github.com/btcsuite/btcd/btcec/README.md new file mode 100644 index 00000000..130bd200 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/README.md @@ -0,0 +1,68 @@ +btcec +===== + +[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcec) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/btcec?status.png)](http://godoc.org/github.com/btcsuite/btcd/btcec) + +Package btcec implements elliptic curve cryptography needed for working with +Bitcoin (secp256k1 only for now). It is designed so that it may be used with the +standard crypto/ecdsa packages provided with go. A comprehensive suite of test +is provided to ensure proper functionality. Package btcec was originally based +on work from ThePiachu which is licensed under the same terms as Go, but it has +signficantly diverged since then. The btcsuite developers original is licensed +under the liberal ISC license. + +Although this package was primarily written for btcd, it has intentionally been +designed so it can be used as a standalone package for any projects needing to +use secp256k1 elliptic curve cryptography. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcec +``` + +## Examples + +* [Sign Message](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--SignMessage) + Demonstrates signing a message with a secp256k1 private key that is first + parsed form raw bytes and serializing the generated signature. + +* [Verify Signature](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--VerifySignature) + Demonstrates verifying a secp256k1 signature against a public key that is + first parsed from raw bytes. The signature is also parsed from raw bytes. + +* [Encryption](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--EncryptMessage) + Demonstrates encrypting a message for a public key that is first parsed from + raw bytes, then decrypting it using the corresponding private key. + +* [Decryption](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--DecryptMessage) + Demonstrates decrypting a message using a private key that is first parsed + from raw bytes. + +## 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 the btcsuite developers. 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 btcec is licensed under the [copyfree](http://copyfree.org) ISC License +except for btcec.go and btcec_test.go which is under the same license as Go. + diff --git a/vendor/github.com/btcsuite/btcd/btcec/btcec.go b/vendor/github.com/btcsuite/btcd/btcec/btcec.go new file mode 100644 index 00000000..fe8ff901 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/btcec.go @@ -0,0 +1,956 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Copyright 2011 ThePiachu. All rights reserved. +// Copyright 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +// References: +// [SECG]: Recommended Elliptic Curve Domain Parameters +// http://www.secg.org/sec2-v2.pdf +// +// [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone) + +// This package operates, internally, on Jacobian coordinates. For a given +// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1) +// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole +// calculation can be performed within the transform (as in ScalarMult and +// ScalarBaseMult). But even for Add and Double, it's faster to apply and +// reverse the transform than to operate in affine coordinates. + +import ( + "crypto/elliptic" + "math/big" + "sync" +) + +var ( + // fieldOne is simply the integer 1 in field representation. It is + // used to avoid needing to create it multiple times during the internal + // arithmetic. + fieldOne = new(fieldVal).SetInt(1) +) + +// KoblitzCurve supports a koblitz curve implementation that fits the ECC Curve +// interface from crypto/elliptic. +type KoblitzCurve struct { + *elliptic.CurveParams + q *big.Int + H int // cofactor of the curve. + + // byteSize is simply the bit size / 8 and is provided for convenience + // since it is calculated repeatedly. + byteSize int + + // bytePoints + bytePoints *[32][256][3]fieldVal + + // The next 6 values are used specifically for endomorphism + // optimizations in ScalarMult. + + // lambda must fulfill lambda^3 = 1 mod N where N is the order of G. + lambda *big.Int + + // beta must fulfill beta^3 = 1 mod P where P is the prime field of the + // curve. + beta *fieldVal + + // See the EndomorphismVectors in gensecp256k1.go to see how these are + // derived. + a1 *big.Int + b1 *big.Int + a2 *big.Int + b2 *big.Int +} + +// Params returns the parameters for the curve. +func (curve *KoblitzCurve) Params() *elliptic.CurveParams { + return curve.CurveParams +} + +// bigAffineToField takes an affine point (x, y) as big integers and converts +// it to an affine point as field values. +func (curve *KoblitzCurve) bigAffineToField(x, y *big.Int) (*fieldVal, *fieldVal) { + x3, y3 := new(fieldVal), new(fieldVal) + x3.SetByteSlice(x.Bytes()) + y3.SetByteSlice(y.Bytes()) + + return x3, y3 +} + +// fieldJacobianToBigAffine takes a Jacobian point (x, y, z) as field values and +// converts it to an affine point as big integers. +func (curve *KoblitzCurve) fieldJacobianToBigAffine(x, y, z *fieldVal) (*big.Int, *big.Int) { + // Inversions are expensive and both point addition and point doubling + // are faster when working with points that have a z value of one. So, + // if the point needs to be converted to affine, go ahead and normalize + // the point itself at the same time as the calculation is the same. + var zInv, tempZ fieldVal + zInv.Set(z).Inverse() // zInv = Z^-1 + tempZ.SquareVal(&zInv) // tempZ = Z^-2 + x.Mul(&tempZ) // X = X/Z^2 (mag: 1) + y.Mul(tempZ.Mul(&zInv)) // Y = Y/Z^3 (mag: 1) + z.SetInt(1) // Z = 1 (mag: 1) + + // Normalize the x and y values. + x.Normalize() + y.Normalize() + + // Convert the field values for the now affine point to big.Ints. + x3, y3 := new(big.Int), new(big.Int) + x3.SetBytes(x.Bytes()[:]) + y3.SetBytes(y.Bytes()[:]) + return x3, y3 +} + +// IsOnCurve returns boolean if the point (x,y) is on the curve. +// Part of the elliptic.Curve interface. This function differs from the +// crypto/elliptic algorithm since a = 0 not -3. +func (curve *KoblitzCurve) IsOnCurve(x, y *big.Int) bool { + // Convert big ints to field values for faster arithmetic. + fx, fy := curve.bigAffineToField(x, y) + + // Elliptic curve equation for secp256k1 is: y^2 = x^3 + 7 + y2 := new(fieldVal).SquareVal(fy).Normalize() + result := new(fieldVal).SquareVal(fx).Mul(fx).AddInt(7).Normalize() + return y2.Equals(result) +} + +// addZ1AndZ2EqualsOne adds two Jacobian points that are already known to have +// z values of 1 and stores the result in (x3, y3, z3). That is to say +// (x1, y1, 1) + (x2, y2, 1) = (x3, y3, z3). It performs faster addition than +// the generic add routine since less arithmetic is needed due to the ability to +// avoid the z value multiplications. +func (curve *KoblitzCurve) addZ1AndZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) { + // To compute the point addition efficiently, this implementation splits + // the equation into intermediate elements which are used to minimize + // the number of field multiplications using the method shown at: + // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl + // + // In particular it performs the calculations using the following: + // H = X2-X1, HH = H^2, I = 4*HH, J = H*I, r = 2*(Y2-Y1), V = X1*I + // X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*Y1*J, Z3 = 2*H + // + // This results in a cost of 4 field multiplications, 2 field squarings, + // 6 field additions, and 5 integer multiplications. + + // When the x coordinates are the same for two points on the curve, the + // y coordinates either must be the same, in which case it is point + // doubling, or they are opposite and the result is the point at + // infinity per the group law for elliptic curve cryptography. + x1.Normalize() + y1.Normalize() + x2.Normalize() + y2.Normalize() + if x1.Equals(x2) { + if y1.Equals(y2) { + // Since x1 == x2 and y1 == y2, point doubling must be + // done, otherwise the addition would end up dividing + // by zero. + curve.doubleJacobian(x1, y1, z1, x3, y3, z3) + return + } + + // Since x1 == x2 and y1 == -y2, the sum is the point at + // infinity per the group law. + x3.SetInt(0) + y3.SetInt(0) + z3.SetInt(0) + return + } + + // Calculate X3, Y3, and Z3 according to the intermediate elements + // breakdown above. + var h, i, j, r, v fieldVal + var negJ, neg2V, negX3 fieldVal + h.Set(x1).Negate(1).Add(x2) // H = X2-X1 (mag: 3) + i.SquareVal(&h).MulInt(4) // I = 4*H^2 (mag: 4) + j.Mul2(&h, &i) // J = H*I (mag: 1) + r.Set(y1).Negate(1).Add(y2).MulInt(2) // r = 2*(Y2-Y1) (mag: 6) + v.Mul2(x1, &i) // V = X1*I (mag: 1) + negJ.Set(&j).Negate(1) // negJ = -J (mag: 2) + neg2V.Set(&v).MulInt(2).Negate(2) // neg2V = -(2*V) (mag: 3) + x3.Set(&r).Square().Add(&negJ).Add(&neg2V) // X3 = r^2-J-2*V (mag: 6) + negX3.Set(x3).Negate(6) // negX3 = -X3 (mag: 7) + j.Mul(y1).MulInt(2).Negate(2) // J = -(2*Y1*J) (mag: 3) + y3.Set(&v).Add(&negX3).Mul(&r).Add(&j) // Y3 = r*(V-X3)-2*Y1*J (mag: 4) + z3.Set(&h).MulInt(2) // Z3 = 2*H (mag: 6) + + // Normalize the resulting field values to a magnitude of 1 as needed. + x3.Normalize() + y3.Normalize() + z3.Normalize() +} + +// addZ1EqualsZ2 adds two Jacobian points that are already known to have the +// same z value and stores the result in (x3, y3, z3). That is to say +// (x1, y1, z1) + (x2, y2, z1) = (x3, y3, z3). It performs faster addition than +// the generic add routine since less arithmetic is needed due to the known +// equivalence. +func (curve *KoblitzCurve) addZ1EqualsZ2(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) { + // To compute the point addition efficiently, this implementation splits + // the equation into intermediate elements which are used to minimize + // the number of field multiplications using a slightly modified version + // of the method shown at: + // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl + // + // In particular it performs the calculations using the following: + // A = X2-X1, B = A^2, C=Y2-Y1, D = C^2, E = X1*B, F = X2*B + // X3 = D-E-F, Y3 = C*(E-X3)-Y1*(F-E), Z3 = Z1*A + // + // This results in a cost of 5 field multiplications, 2 field squarings, + // 9 field additions, and 0 integer multiplications. + + // When the x coordinates are the same for two points on the curve, the + // y coordinates either must be the same, in which case it is point + // doubling, or they are opposite and the result is the point at + // infinity per the group law for elliptic curve cryptography. + x1.Normalize() + y1.Normalize() + x2.Normalize() + y2.Normalize() + if x1.Equals(x2) { + if y1.Equals(y2) { + // Since x1 == x2 and y1 == y2, point doubling must be + // done, otherwise the addition would end up dividing + // by zero. + curve.doubleJacobian(x1, y1, z1, x3, y3, z3) + return + } + + // Since x1 == x2 and y1 == -y2, the sum is the point at + // infinity per the group law. + x3.SetInt(0) + y3.SetInt(0) + z3.SetInt(0) + return + } + + // Calculate X3, Y3, and Z3 according to the intermediate elements + // breakdown above. + var a, b, c, d, e, f fieldVal + var negX1, negY1, negE, negX3 fieldVal + negX1.Set(x1).Negate(1) // negX1 = -X1 (mag: 2) + negY1.Set(y1).Negate(1) // negY1 = -Y1 (mag: 2) + a.Set(&negX1).Add(x2) // A = X2-X1 (mag: 3) + b.SquareVal(&a) // B = A^2 (mag: 1) + c.Set(&negY1).Add(y2) // C = Y2-Y1 (mag: 3) + d.SquareVal(&c) // D = C^2 (mag: 1) + e.Mul2(x1, &b) // E = X1*B (mag: 1) + negE.Set(&e).Negate(1) // negE = -E (mag: 2) + f.Mul2(x2, &b) // F = X2*B (mag: 1) + x3.Add2(&e, &f).Negate(3).Add(&d) // X3 = D-E-F (mag: 5) + negX3.Set(x3).Negate(5).Normalize() // negX3 = -X3 (mag: 1) + y3.Set(y1).Mul(f.Add(&negE)).Negate(3) // Y3 = -(Y1*(F-E)) (mag: 4) + y3.Add(e.Add(&negX3).Mul(&c)) // Y3 = C*(E-X3)+Y3 (mag: 5) + z3.Mul2(z1, &a) // Z3 = Z1*A (mag: 1) + + // Normalize the resulting field values to a magnitude of 1 as needed. + x3.Normalize() + y3.Normalize() +} + +// addZ2EqualsOne adds two Jacobian points when the second point is already +// known to have a z value of 1 (and the z value for the first point is not 1) +// and stores the result in (x3, y3, z3). That is to say (x1, y1, z1) + +// (x2, y2, 1) = (x3, y3, z3). It performs faster addition than the generic +// add routine since less arithmetic is needed due to the ability to avoid +// multiplications by the second point's z value. +func (curve *KoblitzCurve) addZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) { + // To compute the point addition efficiently, this implementation splits + // the equation into intermediate elements which are used to minimize + // the number of field multiplications using the method shown at: + // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl + // + // In particular it performs the calculations using the following: + // Z1Z1 = Z1^2, U2 = X2*Z1Z1, S2 = Y2*Z1*Z1Z1, H = U2-X1, HH = H^2, + // I = 4*HH, J = H*I, r = 2*(S2-Y1), V = X1*I + // X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*Y1*J, Z3 = (Z1+H)^2-Z1Z1-HH + // + // This results in a cost of 7 field multiplications, 4 field squarings, + // 9 field additions, and 4 integer multiplications. + + // When the x coordinates are the same for two points on the curve, the + // y coordinates either must be the same, in which case it is point + // doubling, or they are opposite and the result is the point at + // infinity per the group law for elliptic curve cryptography. Since + // any number of Jacobian coordinates can represent the same affine + // point, the x and y values need to be converted to like terms. Due to + // the assumption made for this function that the second point has a z + // value of 1 (z2=1), the first point is already "converted". + var z1z1, u2, s2 fieldVal + x1.Normalize() + y1.Normalize() + z1z1.SquareVal(z1) // Z1Z1 = Z1^2 (mag: 1) + u2.Set(x2).Mul(&z1z1).Normalize() // U2 = X2*Z1Z1 (mag: 1) + s2.Set(y2).Mul(&z1z1).Mul(z1).Normalize() // S2 = Y2*Z1*Z1Z1 (mag: 1) + if x1.Equals(&u2) { + if y1.Equals(&s2) { + // Since x1 == x2 and y1 == y2, point doubling must be + // done, otherwise the addition would end up dividing + // by zero. + curve.doubleJacobian(x1, y1, z1, x3, y3, z3) + return + } + + // Since x1 == x2 and y1 == -y2, the sum is the point at + // infinity per the group law. + x3.SetInt(0) + y3.SetInt(0) + z3.SetInt(0) + return + } + + // Calculate X3, Y3, and Z3 according to the intermediate elements + // breakdown above. + var h, hh, i, j, r, rr, v fieldVal + var negX1, negY1, negX3 fieldVal + negX1.Set(x1).Negate(1) // negX1 = -X1 (mag: 2) + h.Add2(&u2, &negX1) // H = U2-X1 (mag: 3) + hh.SquareVal(&h) // HH = H^2 (mag: 1) + i.Set(&hh).MulInt(4) // I = 4 * HH (mag: 4) + j.Mul2(&h, &i) // J = H*I (mag: 1) + negY1.Set(y1).Negate(1) // negY1 = -Y1 (mag: 2) + r.Set(&s2).Add(&negY1).MulInt(2) // r = 2*(S2-Y1) (mag: 6) + rr.SquareVal(&r) // rr = r^2 (mag: 1) + v.Mul2(x1, &i) // V = X1*I (mag: 1) + x3.Set(&v).MulInt(2).Add(&j).Negate(3) // X3 = -(J+2*V) (mag: 4) + x3.Add(&rr) // X3 = r^2+X3 (mag: 5) + negX3.Set(x3).Negate(5) // negX3 = -X3 (mag: 6) + y3.Set(y1).Mul(&j).MulInt(2).Negate(2) // Y3 = -(2*Y1*J) (mag: 3) + y3.Add(v.Add(&negX3).Mul(&r)) // Y3 = r*(V-X3)+Y3 (mag: 4) + z3.Add2(z1, &h).Square() // Z3 = (Z1+H)^2 (mag: 1) + z3.Add(z1z1.Add(&hh).Negate(2)) // Z3 = Z3-(Z1Z1+HH) (mag: 4) + + // Normalize the resulting field values to a magnitude of 1 as needed. + x3.Normalize() + y3.Normalize() + z3.Normalize() +} + +// addGeneric adds two Jacobian points (x1, y1, z1) and (x2, y2, z2) without any +// assumptions about the z values of the two points and stores the result in +// (x3, y3, z3). That is to say (x1, y1, z1) + (x2, y2, z2) = (x3, y3, z3). It +// is the slowest of the add routines due to requiring the most arithmetic. +func (curve *KoblitzCurve) addGeneric(x1, y1, z1, x2, y2, z2, x3, y3, z3 *fieldVal) { + // To compute the point addition efficiently, this implementation splits + // the equation into intermediate elements which are used to minimize + // the number of field multiplications using the method shown at: + // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl + // + // In particular it performs the calculations using the following: + // Z1Z1 = Z1^2, Z2Z2 = Z2^2, U1 = X1*Z2Z2, U2 = X2*Z1Z1, S1 = Y1*Z2*Z2Z2 + // S2 = Y2*Z1*Z1Z1, H = U2-U1, I = (2*H)^2, J = H*I, r = 2*(S2-S1) + // V = U1*I + // X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*S1*J, Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2)*H + // + // This results in a cost of 11 field multiplications, 5 field squarings, + // 9 field additions, and 4 integer multiplications. + + // When the x coordinates are the same for two points on the curve, the + // y coordinates either must be the same, in which case it is point + // doubling, or they are opposite and the result is the point at + // infinity. Since any number of Jacobian coordinates can represent the + // same affine point, the x and y values need to be converted to like + // terms. + var z1z1, z2z2, u1, u2, s1, s2 fieldVal + z1z1.SquareVal(z1) // Z1Z1 = Z1^2 (mag: 1) + z2z2.SquareVal(z2) // Z2Z2 = Z2^2 (mag: 1) + u1.Set(x1).Mul(&z2z2).Normalize() // U1 = X1*Z2Z2 (mag: 1) + u2.Set(x2).Mul(&z1z1).Normalize() // U2 = X2*Z1Z1 (mag: 1) + s1.Set(y1).Mul(&z2z2).Mul(z2).Normalize() // S1 = Y1*Z2*Z2Z2 (mag: 1) + s2.Set(y2).Mul(&z1z1).Mul(z1).Normalize() // S2 = Y2*Z1*Z1Z1 (mag: 1) + if u1.Equals(&u2) { + if s1.Equals(&s2) { + // Since x1 == x2 and y1 == y2, point doubling must be + // done, otherwise the addition would end up dividing + // by zero. + curve.doubleJacobian(x1, y1, z1, x3, y3, z3) + return + } + + // Since x1 == x2 and y1 == -y2, the sum is the point at + // infinity per the group law. + x3.SetInt(0) + y3.SetInt(0) + z3.SetInt(0) + return + } + + // Calculate X3, Y3, and Z3 according to the intermediate elements + // breakdown above. + var h, i, j, r, rr, v fieldVal + var negU1, negS1, negX3 fieldVal + negU1.Set(&u1).Negate(1) // negU1 = -U1 (mag: 2) + h.Add2(&u2, &negU1) // H = U2-U1 (mag: 3) + i.Set(&h).MulInt(2).Square() // I = (2*H)^2 (mag: 2) + j.Mul2(&h, &i) // J = H*I (mag: 1) + negS1.Set(&s1).Negate(1) // negS1 = -S1 (mag: 2) + r.Set(&s2).Add(&negS1).MulInt(2) // r = 2*(S2-S1) (mag: 6) + rr.SquareVal(&r) // rr = r^2 (mag: 1) + v.Mul2(&u1, &i) // V = U1*I (mag: 1) + x3.Set(&v).MulInt(2).Add(&j).Negate(3) // X3 = -(J+2*V) (mag: 4) + x3.Add(&rr) // X3 = r^2+X3 (mag: 5) + negX3.Set(x3).Negate(5) // negX3 = -X3 (mag: 6) + y3.Mul2(&s1, &j).MulInt(2).Negate(2) // Y3 = -(2*S1*J) (mag: 3) + y3.Add(v.Add(&negX3).Mul(&r)) // Y3 = r*(V-X3)+Y3 (mag: 4) + z3.Add2(z1, z2).Square() // Z3 = (Z1+Z2)^2 (mag: 1) + z3.Add(z1z1.Add(&z2z2).Negate(2)) // Z3 = Z3-(Z1Z1+Z2Z2) (mag: 4) + z3.Mul(&h) // Z3 = Z3*H (mag: 1) + + // Normalize the resulting field values to a magnitude of 1 as needed. + x3.Normalize() + y3.Normalize() +} + +// addJacobian adds the passed Jacobian points (x1, y1, z1) and (x2, y2, z2) +// together and stores the result in (x3, y3, z3). +func (curve *KoblitzCurve) addJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3 *fieldVal) { + // A point at infinity is the identity according to the group law for + // elliptic curve cryptography. Thus, ∞ + P = P and P + ∞ = P. + if (x1.IsZero() && y1.IsZero()) || z1.IsZero() { + x3.Set(x2) + y3.Set(y2) + z3.Set(z2) + return + } + if (x2.IsZero() && y2.IsZero()) || z2.IsZero() { + x3.Set(x1) + y3.Set(y1) + z3.Set(z1) + return + } + + // Faster point addition can be achieved when certain assumptions are + // met. For example, when both points have the same z value, arithmetic + // on the z values can be avoided. This section thus checks for these + // conditions and calls an appropriate add function which is accelerated + // by using those assumptions. + z1.Normalize() + z2.Normalize() + isZ1One := z1.Equals(fieldOne) + isZ2One := z2.Equals(fieldOne) + switch { + case isZ1One && isZ2One: + curve.addZ1AndZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3) + return + case z1.Equals(z2): + curve.addZ1EqualsZ2(x1, y1, z1, x2, y2, x3, y3, z3) + return + case isZ2One: + curve.addZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3) + return + } + + // None of the above assumptions are true, so fall back to generic + // point addition. + curve.addGeneric(x1, y1, z1, x2, y2, z2, x3, y3, z3) +} + +// Add returns the sum of (x1,y1) and (x2,y2). Part of the elliptic.Curve +// interface. +func (curve *KoblitzCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + // A point at infinity is the identity according to the group law for + // elliptic curve cryptography. Thus, ∞ + P = P and P + ∞ = P. + if x1.Sign() == 0 && y1.Sign() == 0 { + return x2, y2 + } + if x2.Sign() == 0 && y2.Sign() == 0 { + return x1, y1 + } + + // Convert the affine coordinates from big integers to field values + // and do the point addition in Jacobian projective space. + fx1, fy1 := curve.bigAffineToField(x1, y1) + fx2, fy2 := curve.bigAffineToField(x2, y2) + fx3, fy3, fz3 := new(fieldVal), new(fieldVal), new(fieldVal) + fOne := new(fieldVal).SetInt(1) + curve.addJacobian(fx1, fy1, fOne, fx2, fy2, fOne, fx3, fy3, fz3) + + // Convert the Jacobian coordinate field values back to affine big + // integers. + return curve.fieldJacobianToBigAffine(fx3, fy3, fz3) +} + +// doubleZ1EqualsOne performs point doubling on the passed Jacobian point +// when the point is already known to have a z value of 1 and stores +// the result in (x3, y3, z3). That is to say (x3, y3, z3) = 2*(x1, y1, 1). It +// performs faster point doubling than the generic routine since less arithmetic +// is needed due to the ability to avoid multiplication by the z value. +func (curve *KoblitzCurve) doubleZ1EqualsOne(x1, y1, x3, y3, z3 *fieldVal) { + // This function uses the assumptions that z1 is 1, thus the point + // doubling formulas reduce to: + // + // X3 = (3*X1^2)^2 - 8*X1*Y1^2 + // Y3 = (3*X1^2)*(4*X1*Y1^2 - X3) - 8*Y1^4 + // Z3 = 2*Y1 + // + // To compute the above efficiently, this implementation splits the + // equation into intermediate elements which are used to minimize the + // number of field multiplications in favor of field squarings which + // are roughly 35% faster than field multiplications with the current + // implementation at the time this was written. + // + // This uses a slightly modified version of the method shown at: + // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl + // + // In particular it performs the calculations using the following: + // A = X1^2, B = Y1^2, C = B^2, D = 2*((X1+B)^2-A-C) + // E = 3*A, F = E^2, X3 = F-2*D, Y3 = E*(D-X3)-8*C + // Z3 = 2*Y1 + // + // This results in a cost of 1 field multiplication, 5 field squarings, + // 6 field additions, and 5 integer multiplications. + var a, b, c, d, e, f fieldVal + z3.Set(y1).MulInt(2) // Z3 = 2*Y1 (mag: 2) + a.SquareVal(x1) // A = X1^2 (mag: 1) + b.SquareVal(y1) // B = Y1^2 (mag: 1) + c.SquareVal(&b) // C = B^2 (mag: 1) + b.Add(x1).Square() // B = (X1+B)^2 (mag: 1) + d.Set(&a).Add(&c).Negate(2) // D = -(A+C) (mag: 3) + d.Add(&b).MulInt(2) // D = 2*(B+D)(mag: 8) + e.Set(&a).MulInt(3) // E = 3*A (mag: 3) + f.SquareVal(&e) // F = E^2 (mag: 1) + x3.Set(&d).MulInt(2).Negate(16) // X3 = -(2*D) (mag: 17) + x3.Add(&f) // X3 = F+X3 (mag: 18) + f.Set(x3).Negate(18).Add(&d).Normalize() // F = D-X3 (mag: 1) + y3.Set(&c).MulInt(8).Negate(8) // Y3 = -(8*C) (mag: 9) + y3.Add(f.Mul(&e)) // Y3 = E*F+Y3 (mag: 10) + + // Normalize the field values back to a magnitude of 1. + x3.Normalize() + y3.Normalize() + z3.Normalize() +} + +// doubleGeneric performs point doubling on the passed Jacobian point without +// any assumptions about the z value and stores the result in (x3, y3, z3). +// That is to say (x3, y3, z3) = 2*(x1, y1, z1). It is the slowest of the point +// doubling routines due to requiring the most arithmetic. +func (curve *KoblitzCurve) doubleGeneric(x1, y1, z1, x3, y3, z3 *fieldVal) { + // Point doubling formula for Jacobian coordinates for the secp256k1 + // curve: + // X3 = (3*X1^2)^2 - 8*X1*Y1^2 + // Y3 = (3*X1^2)*(4*X1*Y1^2 - X3) - 8*Y1^4 + // Z3 = 2*Y1*Z1 + // + // To compute the above efficiently, this implementation splits the + // equation into intermediate elements which are used to minimize the + // number of field multiplications in favor of field squarings which + // are roughly 35% faster than field multiplications with the current + // implementation at the time this was written. + // + // This uses a slightly modified version of the method shown at: + // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + // + // In particular it performs the calculations using the following: + // A = X1^2, B = Y1^2, C = B^2, D = 2*((X1+B)^2-A-C) + // E = 3*A, F = E^2, X3 = F-2*D, Y3 = E*(D-X3)-8*C + // Z3 = 2*Y1*Z1 + // + // This results in a cost of 1 field multiplication, 5 field squarings, + // 6 field additions, and 5 integer multiplications. + var a, b, c, d, e, f fieldVal + z3.Mul2(y1, z1).MulInt(2) // Z3 = 2*Y1*Z1 (mag: 2) + a.SquareVal(x1) // A = X1^2 (mag: 1) + b.SquareVal(y1) // B = Y1^2 (mag: 1) + c.SquareVal(&b) // C = B^2 (mag: 1) + b.Add(x1).Square() // B = (X1+B)^2 (mag: 1) + d.Set(&a).Add(&c).Negate(2) // D = -(A+C) (mag: 3) + d.Add(&b).MulInt(2) // D = 2*(B+D)(mag: 8) + e.Set(&a).MulInt(3) // E = 3*A (mag: 3) + f.SquareVal(&e) // F = E^2 (mag: 1) + x3.Set(&d).MulInt(2).Negate(16) // X3 = -(2*D) (mag: 17) + x3.Add(&f) // X3 = F+X3 (mag: 18) + f.Set(x3).Negate(18).Add(&d).Normalize() // F = D-X3 (mag: 1) + y3.Set(&c).MulInt(8).Negate(8) // Y3 = -(8*C) (mag: 9) + y3.Add(f.Mul(&e)) // Y3 = E*F+Y3 (mag: 10) + + // Normalize the field values back to a magnitude of 1. + x3.Normalize() + y3.Normalize() + z3.Normalize() +} + +// doubleJacobian doubles the passed Jacobian point (x1, y1, z1) and stores the +// result in (x3, y3, z3). +func (curve *KoblitzCurve) doubleJacobian(x1, y1, z1, x3, y3, z3 *fieldVal) { + // Doubling a point at infinity is still infinity. + if y1.IsZero() || z1.IsZero() { + x3.SetInt(0) + y3.SetInt(0) + z3.SetInt(0) + return + } + + // Slightly faster point doubling can be achieved when the z value is 1 + // by avoiding the multiplication on the z value. This section calls + // a point doubling function which is accelerated by using that + // assumption when possible. + if z1.Normalize().Equals(fieldOne) { + curve.doubleZ1EqualsOne(x1, y1, x3, y3, z3) + return + } + + // Fall back to generic point doubling which works with arbitrary z + // values. + curve.doubleGeneric(x1, y1, z1, x3, y3, z3) +} + +// Double returns 2*(x1,y1). Part of the elliptic.Curve interface. +func (curve *KoblitzCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + if y1.Sign() == 0 { + return new(big.Int), new(big.Int) + } + + // Convert the affine coordinates from big integers to field values + // and do the point doubling in Jacobian projective space. + fx1, fy1 := curve.bigAffineToField(x1, y1) + fx3, fy3, fz3 := new(fieldVal), new(fieldVal), new(fieldVal) + fOne := new(fieldVal).SetInt(1) + curve.doubleJacobian(fx1, fy1, fOne, fx3, fy3, fz3) + + // Convert the Jacobian coordinate field values back to affine big + // integers. + return curve.fieldJacobianToBigAffine(fx3, fy3, fz3) +} + +// splitK returns a balanced length-two representation of k and their signs. +// This is algorithm 3.74 from [GECC]. +// +// One thing of note about this algorithm is that no matter what c1 and c2 are, +// the final equation of k = k1 + k2 * lambda (mod n) will hold. This is +// provable mathematically due to how a1/b1/a2/b2 are computed. +// +// c1 and c2 are chosen to minimize the max(k1,k2). +func (curve *KoblitzCurve) splitK(k []byte) ([]byte, []byte, int, int) { + // All math here is done with big.Int, which is slow. + // At some point, it might be useful to write something similar to + // fieldVal but for N instead of P as the prime field if this ends up + // being a bottleneck. + bigIntK := new(big.Int) + c1, c2 := new(big.Int), new(big.Int) + tmp1, tmp2 := new(big.Int), new(big.Int) + k1, k2 := new(big.Int), new(big.Int) + + bigIntK.SetBytes(k) + // c1 = round(b2 * k / n) from step 4. + // Rounding isn't really necessary and costs too much, hence skipped + c1.Mul(curve.b2, bigIntK) + c1.Div(c1, curve.N) + // c2 = round(b1 * k / n) from step 4 (sign reversed to optimize one step) + // Rounding isn't really necessary and costs too much, hence skipped + c2.Mul(curve.b1, bigIntK) + c2.Div(c2, curve.N) + // k1 = k - c1 * a1 - c2 * a2 from step 5 (note c2's sign is reversed) + tmp1.Mul(c1, curve.a1) + tmp2.Mul(c2, curve.a2) + k1.Sub(bigIntK, tmp1) + k1.Add(k1, tmp2) + // k2 = - c1 * b1 - c2 * b2 from step 5 (note c2's sign is reversed) + tmp1.Mul(c1, curve.b1) + tmp2.Mul(c2, curve.b2) + k2.Sub(tmp2, tmp1) + + // Note Bytes() throws out the sign of k1 and k2. This matters + // since k1 and/or k2 can be negative. Hence, we pass that + // back separately. + return k1.Bytes(), k2.Bytes(), k1.Sign(), k2.Sign() +} + +// moduloReduce reduces k from more than 32 bytes to 32 bytes and under. This +// is done by doing a simple modulo curve.N. We can do this since G^N = 1 and +// thus any other valid point on the elliptic curve has the same order. +func (curve *KoblitzCurve) moduloReduce(k []byte) []byte { + // Since the order of G is curve.N, we can use a much smaller number + // by doing modulo curve.N + if len(k) > curve.byteSize { + // Reduce k by performing modulo curve.N. + tmpK := new(big.Int).SetBytes(k) + tmpK.Mod(tmpK, curve.N) + return tmpK.Bytes() + } + + return k +} + +// NAF takes a positive integer k and returns the Non-Adjacent Form (NAF) as two +// byte slices. The first is where 1s will be. The second is where -1s will +// be. NAF is convenient in that on average, only 1/3rd of its values are +// non-zero. This is algorithm 3.30 from [GECC]. +// +// Essentially, this makes it possible to minimize the number of operations +// since the resulting ints returned will be at least 50% 0s. +func NAF(k []byte) ([]byte, []byte) { + // The essence of this algorithm is that whenever we have consecutive 1s + // in the binary, we want to put a -1 in the lowest bit and get a bunch + // of 0s up to the highest bit of consecutive 1s. This is due to this + // identity: + // 2^n + 2^(n-1) + 2^(n-2) + ... + 2^(n-k) = 2^(n+1) - 2^(n-k) + // + // The algorithm thus may need to go 1 more bit than the length of the + // bits we actually have, hence bits being 1 bit longer than was + // necessary. Since we need to know whether adding will cause a carry, + // we go from right-to-left in this addition. + var carry, curIsOne, nextIsOne bool + // these default to zero + retPos := make([]byte, len(k)+1) + retNeg := make([]byte, len(k)+1) + for i := len(k) - 1; i >= 0; i-- { + curByte := k[i] + for j := uint(0); j < 8; j++ { + curIsOne = curByte&1 == 1 + if j == 7 { + if i == 0 { + nextIsOne = false + } else { + nextIsOne = k[i-1]&1 == 1 + } + } else { + nextIsOne = curByte&2 == 2 + } + if carry { + if curIsOne { + // This bit is 1, so continue to carry + // and don't need to do anything. + } else { + // We've hit a 0 after some number of + // 1s. + if nextIsOne { + // Start carrying again since + // a new sequence of 1s is + // starting. + retNeg[i+1] += 1 << j + } else { + // Stop carrying since 1s have + // stopped. + carry = false + retPos[i+1] += 1 << j + } + } + } else if curIsOne { + if nextIsOne { + // If this is the start of at least 2 + // consecutive 1s, set the current one + // to -1 and start carrying. + retNeg[i+1] += 1 << j + carry = true + } else { + // This is a singleton, not consecutive + // 1s. + retPos[i+1] += 1 << j + } + } + curByte >>= 1 + } + } + if carry { + retPos[0] = 1 + return retPos, retNeg + } + return retPos[1:], retNeg[1:] +} + +// ScalarMult returns k*(Bx, By) where k is a big endian integer. +// Part of the elliptic.Curve interface. +func (curve *KoblitzCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { + // Point Q = ∞ (point at infinity). + qx, qy, qz := new(fieldVal), new(fieldVal), new(fieldVal) + + // Decompose K into k1 and k2 in order to halve the number of EC ops. + // See Algorithm 3.74 in [GECC]. + k1, k2, signK1, signK2 := curve.splitK(curve.moduloReduce(k)) + + // The main equation here to remember is: + // k * P = k1 * P + k2 * ϕ(P) + // + // P1 below is P in the equation, P2 below is ϕ(P) in the equation + p1x, p1y := curve.bigAffineToField(Bx, By) + p1yNeg := new(fieldVal).NegateVal(p1y, 1) + p1z := new(fieldVal).SetInt(1) + + // NOTE: ϕ(x,y) = (βx,y). The Jacobian z coordinate is 1, so this math + // goes through. + p2x := new(fieldVal).Mul2(p1x, curve.beta) + p2y := new(fieldVal).Set(p1y) + p2yNeg := new(fieldVal).NegateVal(p2y, 1) + p2z := new(fieldVal).SetInt(1) + + // Flip the positive and negative values of the points as needed + // depending on the signs of k1 and k2. As mentioned in the equation + // above, each of k1 and k2 are multiplied by the respective point. + // Since -k * P is the same thing as k * -P, and the group law for + // elliptic curves states that P(x, y) = -P(x, -y), it's faster and + // simplifies the code to just make the point negative. + if signK1 == -1 { + p1y, p1yNeg = p1yNeg, p1y + } + if signK2 == -1 { + p2y, p2yNeg = p2yNeg, p2y + } + + // NAF versions of k1 and k2 should have a lot more zeros. + // + // The Pos version of the bytes contain the +1s and the Neg versions + // contain the -1s. + k1PosNAF, k1NegNAF := NAF(k1) + k2PosNAF, k2NegNAF := NAF(k2) + k1Len := len(k1PosNAF) + k2Len := len(k2PosNAF) + + m := k1Len + if m < k2Len { + m = k2Len + } + + // Add left-to-right using the NAF optimization. See algorithm 3.77 + // from [GECC]. This should be faster overall since there will be a lot + // more instances of 0, hence reducing the number of Jacobian additions + // at the cost of 1 possible extra doubling. + var k1BytePos, k1ByteNeg, k2BytePos, k2ByteNeg byte + for i := 0; i < m; i++ { + // Since we're going left-to-right, pad the front with 0s. + if i < m-k1Len { + k1BytePos = 0 + k1ByteNeg = 0 + } else { + k1BytePos = k1PosNAF[i-(m-k1Len)] + k1ByteNeg = k1NegNAF[i-(m-k1Len)] + } + if i < m-k2Len { + k2BytePos = 0 + k2ByteNeg = 0 + } else { + k2BytePos = k2PosNAF[i-(m-k2Len)] + k2ByteNeg = k2NegNAF[i-(m-k2Len)] + } + + for j := 7; j >= 0; j-- { + // Q = 2 * Q + curve.doubleJacobian(qx, qy, qz, qx, qy, qz) + + if k1BytePos&0x80 == 0x80 { + curve.addJacobian(qx, qy, qz, p1x, p1y, p1z, + qx, qy, qz) + } else if k1ByteNeg&0x80 == 0x80 { + curve.addJacobian(qx, qy, qz, p1x, p1yNeg, p1z, + qx, qy, qz) + } + + if k2BytePos&0x80 == 0x80 { + curve.addJacobian(qx, qy, qz, p2x, p2y, p2z, + qx, qy, qz) + } else if k2ByteNeg&0x80 == 0x80 { + curve.addJacobian(qx, qy, qz, p2x, p2yNeg, p2z, + qx, qy, qz) + } + k1BytePos <<= 1 + k1ByteNeg <<= 1 + k2BytePos <<= 1 + k2ByteNeg <<= 1 + } + } + + // Convert the Jacobian coordinate field values back to affine big.Ints. + return curve.fieldJacobianToBigAffine(qx, qy, qz) +} + +// ScalarBaseMult returns k*G where G is the base point of the group and k is a +// big endian integer. +// Part of the elliptic.Curve interface. +func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { + newK := curve.moduloReduce(k) + diff := len(curve.bytePoints) - len(newK) + + // Point Q = ∞ (point at infinity). + qx, qy, qz := new(fieldVal), new(fieldVal), new(fieldVal) + + // curve.bytePoints has all 256 byte points for each 8-bit window. The + // strategy is to add up the byte points. This is best understood by + // expressing k in base-256 which it already sort of is. + // Each "digit" in the 8-bit window can be looked up using bytePoints + // and added together. + for i, byteVal := range newK { + p := curve.bytePoints[diff+i][byteVal] + curve.addJacobian(qx, qy, qz, &p[0], &p[1], &p[2], qx, qy, qz) + } + return curve.fieldJacobianToBigAffine(qx, qy, qz) +} + +// QPlus1Div4 returns the Q+1/4 constant for the curve for use in calculating +// square roots via exponention. +func (curve *KoblitzCurve) QPlus1Div4() *big.Int { + return curve.q +} + +var initonce sync.Once +var secp256k1 KoblitzCurve + +func initAll() { + initS256() +} + +// fromHex converts the passed hex string into a big integer pointer and will +// panic is there is an error. This is only provided for the hard-coded +// constants so errors in the source code can bet detected. It will only (and +// must only) be called for initialization purposes. +func fromHex(s string) *big.Int { + r, ok := new(big.Int).SetString(s, 16) + if !ok { + panic("invalid hex in source file: " + s) + } + return r +} + +func initS256() { + // Curve parameters taken from [SECG] section 2.4.1. + secp256k1.CurveParams = new(elliptic.CurveParams) + secp256k1.P = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F") + secp256k1.N = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141") + secp256k1.B = fromHex("0000000000000000000000000000000000000000000000000000000000000007") + secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") + secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") + secp256k1.BitSize = 256 + secp256k1.H = 1 + secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P, + big.NewInt(1)), big.NewInt(4)) + + // Provided for convenience since this gets computed repeatedly. + secp256k1.byteSize = secp256k1.BitSize / 8 + + // Deserialize and set the pre-computed table used to accelerate scalar + // base multiplication. This is hard-coded data, so any errors are + // panics because it means something is wrong in the source code. + if err := loadS256BytePoints(); err != nil { + panic(err) + } + + // Next 6 constants are from Hal Finney's bitcointalk.org post: + // https://bitcointalk.org/index.php?topic=3238.msg45565#msg45565 + // May he rest in peace. + // + // They have also been independently derived from the code in the + // EndomorphismVectors function in gensecp256k1.go. + secp256k1.lambda = fromHex("5363AD4CC05C30E0A5261C028812645A122E22EA20816678DF02967C1B23BD72") + secp256k1.beta = new(fieldVal).SetHex("7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE") + secp256k1.a1 = fromHex("3086D221A7D46BCDE86C90E49284EB15") + secp256k1.b1 = fromHex("-E4437ED6010E88286F547FA90ABFE4C3") + secp256k1.a2 = fromHex("114CA50F7A8E2F3F657C1108D9D44CFD8") + secp256k1.b2 = fromHex("3086D221A7D46BCDE86C90E49284EB15") + + // Alternatively, we can use the parameters below, however, they seem + // to be about 8% slower. + // secp256k1.lambda = fromHex("AC9C52B33FA3CF1F5AD9E3FD77ED9BA4A880B9FC8EC739C2E0CFC810B51283CE") + // secp256k1.beta = new(fieldVal).SetHex("851695D49A83F8EF919BB86153CBCB16630FB68AED0A766A3EC693D68E6AFA40") + // secp256k1.a1 = fromHex("E4437ED6010E88286F547FA90ABFE4C3") + // secp256k1.b1 = fromHex("-3086D221A7D46BCDE86C90E49284EB15") + // secp256k1.a2 = fromHex("3086D221A7D46BCDE86C90E49284EB15") + // secp256k1.b2 = fromHex("114CA50F7A8E2F3F657C1108D9D44CFD8") +} + +// S256 returns a Curve which implements secp256k1. +func S256() *KoblitzCurve { + initonce.Do(initAll) + return &secp256k1 +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/ciphering.go b/vendor/github.com/btcsuite/btcd/btcec/ciphering.go new file mode 100644 index 00000000..b18c9b7a --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/ciphering.go @@ -0,0 +1,216 @@ +// Copyright (c) 2015-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "crypto/sha512" + "errors" + "io" +) + +var ( + // ErrInvalidMAC occurs when Message Authentication Check (MAC) fails + // during decryption. This happens because of either invalid private key or + // corrupt ciphertext. + ErrInvalidMAC = errors.New("invalid mac hash") + + // errInputTooShort occurs when the input ciphertext to the Decrypt + // function is less than 134 bytes long. + errInputTooShort = errors.New("ciphertext too short") + + // errUnsupportedCurve occurs when the first two bytes of the encrypted + // text aren't 0x02CA (= 712 = secp256k1, from OpenSSL). + errUnsupportedCurve = errors.New("unsupported curve") + + errInvalidXLength = errors.New("invalid X length, must be 32") + errInvalidYLength = errors.New("invalid Y length, must be 32") + errInvalidPadding = errors.New("invalid PKCS#7 padding") + + // 0x02CA = 714 + ciphCurveBytes = [2]byte{0x02, 0xCA} + // 0x20 = 32 + ciphCoordLength = [2]byte{0x00, 0x20} +) + +// GenerateSharedSecret generates a shared secret based on a private key and a +// public key using Diffie-Hellman key exchange (ECDH) (RFC 4753). +// RFC5903 Section 9 states we should only return x. +func GenerateSharedSecret(privkey *PrivateKey, pubkey *PublicKey) []byte { + x, _ := pubkey.Curve.ScalarMult(pubkey.X, pubkey.Y, privkey.D.Bytes()) + return x.Bytes() +} + +// Encrypt encrypts data for the target public key using AES-256-CBC. It also +// generates a private key (the pubkey of which is also in the output). The only +// supported curve is secp256k1. The `structure' that it encodes everything into +// is: +// +// struct { +// // Initialization Vector used for AES-256-CBC +// IV [16]byte +// // Public Key: curve(2) + len_of_pubkeyX(2) + pubkeyX + +// // len_of_pubkeyY(2) + pubkeyY (curve = 714) +// PublicKey [70]byte +// // Cipher text +// Data []byte +// // HMAC-SHA-256 Message Authentication Code +// HMAC [32]byte +// } +// +// The primary aim is to ensure byte compatibility with Pyelliptic. Also, refer +// to section 5.8.1 of ANSI X9.63 for rationale on this format. +func Encrypt(pubkey *PublicKey, in []byte) ([]byte, error) { + ephemeral, err := NewPrivateKey(S256()) + if err != nil { + return nil, err + } + ecdhKey := GenerateSharedSecret(ephemeral, pubkey) + derivedKey := sha512.Sum512(ecdhKey) + keyE := derivedKey[:32] + keyM := derivedKey[32:] + + paddedIn := addPKCSPadding(in) + // IV + Curve params/X/Y + padded plaintext/ciphertext + HMAC-256 + out := make([]byte, aes.BlockSize+70+len(paddedIn)+sha256.Size) + iv := out[:aes.BlockSize] + if _, err = io.ReadFull(rand.Reader, iv); err != nil { + return nil, err + } + // start writing public key + pb := ephemeral.PubKey().SerializeUncompressed() + offset := aes.BlockSize + + // curve and X length + copy(out[offset:offset+4], append(ciphCurveBytes[:], ciphCoordLength[:]...)) + offset += 4 + // X + copy(out[offset:offset+32], pb[1:33]) + offset += 32 + // Y length + copy(out[offset:offset+2], ciphCoordLength[:]) + offset += 2 + // Y + copy(out[offset:offset+32], pb[33:]) + offset += 32 + + // start encryption + block, err := aes.NewCipher(keyE) + if err != nil { + return nil, err + } + mode := cipher.NewCBCEncrypter(block, iv) + mode.CryptBlocks(out[offset:len(out)-sha256.Size], paddedIn) + + // start HMAC-SHA-256 + hm := hmac.New(sha256.New, keyM) + hm.Write(out[:len(out)-sha256.Size]) // everything is hashed + copy(out[len(out)-sha256.Size:], hm.Sum(nil)) // write checksum + + return out, nil +} + +// Decrypt decrypts data that was encrypted using the Encrypt function. +func Decrypt(priv *PrivateKey, in []byte) ([]byte, error) { + // IV + Curve params/X/Y + 1 block + HMAC-256 + if len(in) < aes.BlockSize+70+aes.BlockSize+sha256.Size { + return nil, errInputTooShort + } + + // read iv + iv := in[:aes.BlockSize] + offset := aes.BlockSize + + // start reading pubkey + if !bytes.Equal(in[offset:offset+2], ciphCurveBytes[:]) { + return nil, errUnsupportedCurve + } + offset += 2 + + if !bytes.Equal(in[offset:offset+2], ciphCoordLength[:]) { + return nil, errInvalidXLength + } + offset += 2 + + xBytes := in[offset : offset+32] + offset += 32 + + if !bytes.Equal(in[offset:offset+2], ciphCoordLength[:]) { + return nil, errInvalidYLength + } + offset += 2 + + yBytes := in[offset : offset+32] + offset += 32 + + pb := make([]byte, 65) + pb[0] = byte(0x04) // uncompressed + copy(pb[1:33], xBytes) + copy(pb[33:], yBytes) + // check if (X, Y) lies on the curve and create a Pubkey if it does + pubkey, err := ParsePubKey(pb, S256()) + if err != nil { + return nil, err + } + + // check for cipher text length + if (len(in)-aes.BlockSize-offset-sha256.Size)%aes.BlockSize != 0 { + return nil, errInvalidPadding // not padded to 16 bytes + } + + // read hmac + messageMAC := in[len(in)-sha256.Size:] + + // generate shared secret + ecdhKey := GenerateSharedSecret(priv, pubkey) + derivedKey := sha512.Sum512(ecdhKey) + keyE := derivedKey[:32] + keyM := derivedKey[32:] + + // verify mac + hm := hmac.New(sha256.New, keyM) + hm.Write(in[:len(in)-sha256.Size]) // everything is hashed + expectedMAC := hm.Sum(nil) + if !hmac.Equal(messageMAC, expectedMAC) { + return nil, ErrInvalidMAC + } + + // start decryption + block, err := aes.NewCipher(keyE) + if err != nil { + return nil, err + } + mode := cipher.NewCBCDecrypter(block, iv) + // same length as ciphertext + plaintext := make([]byte, len(in)-offset-sha256.Size) + mode.CryptBlocks(plaintext, in[offset:len(in)-sha256.Size]) + + return removePKCSPadding(plaintext) +} + +// Implement PKCS#7 padding with block size of 16 (AES block size). + +// addPKCSPadding adds padding to a block of data +func addPKCSPadding(src []byte) []byte { + padding := aes.BlockSize - len(src)%aes.BlockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(src, padtext...) +} + +// removePKCSPadding removes padding from data that was added with addPKCSPadding +func removePKCSPadding(src []byte) ([]byte, error) { + length := len(src) + padLength := int(src[length-1]) + if padLength > aes.BlockSize || length < aes.BlockSize { + return nil, errInvalidPadding + } + + return src[:length-padLength], nil +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/doc.go b/vendor/github.com/btcsuite/btcd/btcec/doc.go new file mode 100644 index 00000000..fa8346ab --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/doc.go @@ -0,0 +1,21 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package btcec implements support for the elliptic curves needed for bitcoin. + +Bitcoin uses elliptic curve cryptography using koblitz curves +(specifically secp256k1) for cryptographic functions. See +http://www.secg.org/collateral/sec2_final.pdf for details on the +standard. + +This package provides the data structures and functions implementing the +crypto/elliptic Curve interface in order to permit using these curves +with the standard crypto/ecdsa package provided with go. Helper +functionality is provided to parse signatures and public keys from +standard formats. It was designed for use with btcd, but should be +general enough for other uses of elliptic curve crypto. It was originally based +on some initial work by ThePiachu, but has significantly diverged since then. +*/ +package btcec diff --git a/vendor/github.com/btcsuite/btcd/btcec/field.go b/vendor/github.com/btcsuite/btcd/btcec/field.go new file mode 100644 index 00000000..0f2be74c --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/field.go @@ -0,0 +1,1223 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2013-2016 Dave Collins +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +// References: +// [HAC]: Handbook of Applied Cryptography Menezes, van Oorschot, Vanstone. +// http://cacr.uwaterloo.ca/hac/ + +// All elliptic curve operations for secp256k1 are done in a finite field +// characterized by a 256-bit prime. Given this precision is larger than the +// biggest available native type, obviously some form of bignum math is needed. +// This package implements specialized fixed-precision field arithmetic rather +// than relying on an arbitrary-precision arithmetic package such as math/big +// for dealing with the field math since the size is known. As a result, rather +// large performance gains are achieved by taking advantage of many +// optimizations not available to arbitrary-precision arithmetic and generic +// modular arithmetic algorithms. +// +// There are various ways to internally represent each finite field element. +// For example, the most obvious representation would be to use an array of 4 +// uint64s (64 bits * 4 = 256 bits). However, that representation suffers from +// a couple of issues. First, there is no native Go type large enough to handle +// the intermediate results while adding or multiplying two 64-bit numbers, and +// second there is no space left for overflows when performing the intermediate +// arithmetic between each array element which would lead to expensive carry +// propagation. +// +// Given the above, this implementation represents the the field elements as +// 10 uint32s with each word (array entry) treated as base 2^26. This was +// chosen for the following reasons: +// 1) Most systems at the current time are 64-bit (or at least have 64-bit +// registers available for specialized purposes such as MMX) so the +// intermediate results can typically be done using a native register (and +// using uint64s to avoid the need for additional half-word arithmetic) +// 2) In order to allow addition of the internal words without having to +// propagate the the carry, the max normalized value for each register must +// be less than the number of bits available in the register +// 3) Since we're dealing with 32-bit values, 64-bits of overflow is a +// reasonable choice for #2 +// 4) Given the need for 256-bits of precision and the properties stated in #1, +// #2, and #3, the representation which best accommodates this is 10 uint32s +// with base 2^26 (26 bits * 10 = 260 bits, so the final word only needs 22 +// bits) which leaves the desired 64 bits (32 * 10 = 320, 320 - 256 = 64) for +// overflow +// +// Since it is so important that the field arithmetic is extremely fast for +// high performance crypto, this package does not perform any validation where +// it ordinarily would. For example, some functions only give the correct +// result is the field is normalized and there is no checking to ensure it is. +// While I typically prefer to ensure all state and input is valid for most +// packages, this code is really only used internally and every extra check +// counts. + +import ( + "encoding/hex" +) + +// Constants used to make the code more readable. +const ( + twoBitsMask = 0x3 + fourBitsMask = 0xf + sixBitsMask = 0x3f + eightBitsMask = 0xff +) + +// Constants related to the field representation. +const ( + // fieldWords is the number of words used to internally represent the + // 256-bit value. + fieldWords = 10 + + // fieldBase is the exponent used to form the numeric base of each word. + // 2^(fieldBase*i) where i is the word position. + fieldBase = 26 + + // fieldOverflowBits is the minimum number of "overflow" bits for each + // word in the field value. + fieldOverflowBits = 32 - fieldBase + + // fieldBaseMask is the mask for the bits in each word needed to + // represent the numeric base of each word (except the most significant + // word). + fieldBaseMask = (1 << fieldBase) - 1 + + // fieldMSBBits is the number of bits in the most significant word used + // to represent the value. + fieldMSBBits = 256 - (fieldBase * (fieldWords - 1)) + + // fieldMSBMask is the mask for the bits in the most significant word + // needed to represent the value. + fieldMSBMask = (1 << fieldMSBBits) - 1 + + // fieldPrimeWordZero is word zero of the secp256k1 prime in the + // internal field representation. It is used during negation. + fieldPrimeWordZero = 0x3fffc2f + + // fieldPrimeWordOne is word one of the secp256k1 prime in the + // internal field representation. It is used during negation. + fieldPrimeWordOne = 0x3ffffbf +) + +// fieldVal implements optimized fixed-precision arithmetic over the +// secp256k1 finite field. This means all arithmetic is performed modulo +// 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f. It +// represents each 256-bit value as 10 32-bit integers in base 2^26. This +// provides 6 bits of overflow in each word (10 bits in the most significant +// word) for a total of 64 bits of overflow (9*6 + 10 = 64). It only implements +// the arithmetic needed for elliptic curve operations. +// +// The following depicts the internal representation: +// ----------------------------------------------------------------- +// | n[9] | n[8] | ... | n[0] | +// | 32 bits available | 32 bits available | ... | 32 bits available | +// | 22 bits for value | 26 bits for value | ... | 26 bits for value | +// | 10 bits overflow | 6 bits overflow | ... | 6 bits overflow | +// | Mult: 2^(26*9) | Mult: 2^(26*8) | ... | Mult: 2^(26*0) | +// ----------------------------------------------------------------- +// +// For example, consider the number 2^49 + 1. It would be represented as: +// n[0] = 1 +// n[1] = 2^23 +// n[2..9] = 0 +// +// The full 256-bit value is then calculated by looping i from 9..0 and +// doing sum(n[i] * 2^(26i)) like so: +// n[9] * 2^(26*9) = 0 * 2^234 = 0 +// n[8] * 2^(26*8) = 0 * 2^208 = 0 +// ... +// n[1] * 2^(26*1) = 2^23 * 2^26 = 2^49 +// n[0] * 2^(26*0) = 1 * 2^0 = 1 +// Sum: 0 + 0 + ... + 2^49 + 1 = 2^49 + 1 +type fieldVal struct { + n [10]uint32 +} + +// String returns the field value as a human-readable hex string. +func (f fieldVal) String() string { + t := new(fieldVal).Set(&f).Normalize() + return hex.EncodeToString(t.Bytes()[:]) +} + +// Zero sets the field value to zero. A newly created field value is already +// set to zero. This function can be useful to clear an existing field value +// for reuse. +func (f *fieldVal) Zero() { + f.n[0] = 0 + f.n[1] = 0 + f.n[2] = 0 + f.n[3] = 0 + f.n[4] = 0 + f.n[5] = 0 + f.n[6] = 0 + f.n[7] = 0 + f.n[8] = 0 + f.n[9] = 0 +} + +// Set sets the field value equal to the passed value. +// +// The field value is returned to support chaining. This enables syntax like: +// f := new(fieldVal).Set(f2).Add(1) so that f = f2 + 1 where f2 is not +// modified. +func (f *fieldVal) Set(val *fieldVal) *fieldVal { + *f = *val + return f +} + +// SetInt sets the field value to the passed integer. This is a convenience +// function since it is fairly common to perform some arithemetic with small +// native integers. +// +// The field value is returned to support chaining. This enables syntax such +// as f := new(fieldVal).SetInt(2).Mul(f2) so that f = 2 * f2. +func (f *fieldVal) SetInt(ui uint) *fieldVal { + f.Zero() + f.n[0] = uint32(ui) + return f +} + +// SetBytes packs the passed 32-byte big-endian value into the internal field +// value representation. +// +// The field value is returned to support chaining. This enables syntax like: +// f := new(fieldVal).SetBytes(byteArray).Mul(f2) so that f = ba * f2. +func (f *fieldVal) SetBytes(b *[32]byte) *fieldVal { + // Pack the 256 total bits across the 10 uint32 words with a max of + // 26-bits per word. This could be done with a couple of for loops, + // but this unrolled version is significantly faster. Benchmarks show + // this is about 34 times faster than the variant which uses loops. + f.n[0] = uint32(b[31]) | uint32(b[30])<<8 | uint32(b[29])<<16 | + (uint32(b[28])&twoBitsMask)<<24 + f.n[1] = uint32(b[28])>>2 | uint32(b[27])<<6 | uint32(b[26])<<14 | + (uint32(b[25])&fourBitsMask)<<22 + f.n[2] = uint32(b[25])>>4 | uint32(b[24])<<4 | uint32(b[23])<<12 | + (uint32(b[22])&sixBitsMask)<<20 + f.n[3] = uint32(b[22])>>6 | uint32(b[21])<<2 | uint32(b[20])<<10 | + uint32(b[19])<<18 + f.n[4] = uint32(b[18]) | uint32(b[17])<<8 | uint32(b[16])<<16 | + (uint32(b[15])&twoBitsMask)<<24 + f.n[5] = uint32(b[15])>>2 | uint32(b[14])<<6 | uint32(b[13])<<14 | + (uint32(b[12])&fourBitsMask)<<22 + f.n[6] = uint32(b[12])>>4 | uint32(b[11])<<4 | uint32(b[10])<<12 | + (uint32(b[9])&sixBitsMask)<<20 + f.n[7] = uint32(b[9])>>6 | uint32(b[8])<<2 | uint32(b[7])<<10 | + uint32(b[6])<<18 + f.n[8] = uint32(b[5]) | uint32(b[4])<<8 | uint32(b[3])<<16 | + (uint32(b[2])&twoBitsMask)<<24 + f.n[9] = uint32(b[2])>>2 | uint32(b[1])<<6 | uint32(b[0])<<14 + return f +} + +// SetByteSlice packs the passed big-endian value into the internal field value +// representation. Only the first 32-bytes are used. As a result, it is up to +// the caller to ensure numbers of the appropriate size are used or the value +// will be truncated. +// +// The field value is returned to support chaining. This enables syntax like: +// f := new(fieldVal).SetByteSlice(byteSlice) +func (f *fieldVal) SetByteSlice(b []byte) *fieldVal { + var b32 [32]byte + for i := 0; i < len(b); i++ { + if i < 32 { + b32[i+(32-len(b))] = b[i] + } + } + return f.SetBytes(&b32) +} + +// SetHex decodes the passed big-endian hex string into the internal field value +// representation. Only the first 32-bytes are used. +// +// The field value is returned to support chaining. This enables syntax like: +// f := new(fieldVal).SetHex("0abc").Add(1) so that f = 0x0abc + 1 +func (f *fieldVal) SetHex(hexString string) *fieldVal { + if len(hexString)%2 != 0 { + hexString = "0" + hexString + } + bytes, _ := hex.DecodeString(hexString) + return f.SetByteSlice(bytes) +} + +// Normalize normalizes the internal field words into the desired range and +// performs fast modular reduction over the secp256k1 prime by making use of the +// special form of the prime. +func (f *fieldVal) Normalize() *fieldVal { + // The field representation leaves 6 bits of overflow in each word so + // intermediate calculations can be performed without needing to + // propagate the carry to each higher word during the calculations. In + // order to normalize, we need to "compact" the full 256-bit value to + // the right while propagating any carries through to the high order + // word. + // + // Since this field is doing arithmetic modulo the secp256k1 prime, we + // also need to perform modular reduction over the prime. + // + // Per [HAC] section 14.3.4: Reduction method of moduli of special form, + // when the modulus is of the special form m = b^t - c, highly efficient + // reduction can be achieved. + // + // The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits + // this criteria. + // + // 4294968273 in field representation (base 2^26) is: + // n[0] = 977 + // n[1] = 64 + // That is to say (2^26 * 64) + 977 = 4294968273 + // + // The algorithm presented in the referenced section typically repeats + // until the quotient is zero. However, due to our field representation + // we already know to within one reduction how many times we would need + // to repeat as it's the uppermost bits of the high order word. Thus we + // can simply multiply the magnitude by the field representation of the + // prime and do a single iteration. After this step there might be an + // additional carry to bit 256 (bit 22 of the high order word). + t9 := f.n[9] + m := t9 >> fieldMSBBits + t9 = t9 & fieldMSBMask + t0 := f.n[0] + m*977 + t1 := (t0 >> fieldBase) + f.n[1] + (m << 6) + t0 = t0 & fieldBaseMask + t2 := (t1 >> fieldBase) + f.n[2] + t1 = t1 & fieldBaseMask + t3 := (t2 >> fieldBase) + f.n[3] + t2 = t2 & fieldBaseMask + t4 := (t3 >> fieldBase) + f.n[4] + t3 = t3 & fieldBaseMask + t5 := (t4 >> fieldBase) + f.n[5] + t4 = t4 & fieldBaseMask + t6 := (t5 >> fieldBase) + f.n[6] + t5 = t5 & fieldBaseMask + t7 := (t6 >> fieldBase) + f.n[7] + t6 = t6 & fieldBaseMask + t8 := (t7 >> fieldBase) + f.n[8] + t7 = t7 & fieldBaseMask + t9 = (t8 >> fieldBase) + t9 + t8 = t8 & fieldBaseMask + + // At this point, the magnitude is guaranteed to be one, however, the + // value could still be greater than the prime if there was either a + // carry through to bit 256 (bit 22 of the higher order word) or the + // value is greater than or equal to the field characteristic. The + // following determines if either or these conditions are true and does + // the final reduction in constant time. + // + // Note that the if/else statements here intentionally do the bitwise + // operators even when it won't change the value to ensure constant time + // between the branches. Also note that 'm' will be zero when neither + // of the aforementioned conditions are true and the value will not be + // changed when 'm' is zero. + m = 1 + if t9 == fieldMSBMask { + m &= 1 + } else { + m &= 0 + } + if t2&t3&t4&t5&t6&t7&t8 == fieldBaseMask { + m &= 1 + } else { + m &= 0 + } + if ((t0+977)>>fieldBase + t1 + 64) > fieldBaseMask { + m &= 1 + } else { + m &= 0 + } + if t9>>fieldMSBBits != 0 { + m |= 1 + } else { + m |= 0 + } + t0 = t0 + m*977 + t1 = (t0 >> fieldBase) + t1 + (m << 6) + t0 = t0 & fieldBaseMask + t2 = (t1 >> fieldBase) + t2 + t1 = t1 & fieldBaseMask + t3 = (t2 >> fieldBase) + t3 + t2 = t2 & fieldBaseMask + t4 = (t3 >> fieldBase) + t4 + t3 = t3 & fieldBaseMask + t5 = (t4 >> fieldBase) + t5 + t4 = t4 & fieldBaseMask + t6 = (t5 >> fieldBase) + t6 + t5 = t5 & fieldBaseMask + t7 = (t6 >> fieldBase) + t7 + t6 = t6 & fieldBaseMask + t8 = (t7 >> fieldBase) + t8 + t7 = t7 & fieldBaseMask + t9 = (t8 >> fieldBase) + t9 + t8 = t8 & fieldBaseMask + t9 = t9 & fieldMSBMask // Remove potential multiple of 2^256. + + // Finally, set the normalized and reduced words. + f.n[0] = t0 + f.n[1] = t1 + f.n[2] = t2 + f.n[3] = t3 + f.n[4] = t4 + f.n[5] = t5 + f.n[6] = t6 + f.n[7] = t7 + f.n[8] = t8 + f.n[9] = t9 + return f +} + +// PutBytes unpacks the field value to a 32-byte big-endian value using the +// passed byte array. There is a similar function, Bytes, which unpacks the +// field value into a new array and returns that. This version is provided +// since it can be useful to cut down on the number of allocations by allowing +// the caller to reuse a buffer. +// +// The field value must be normalized for this function to return the correct +// result. +func (f *fieldVal) PutBytes(b *[32]byte) { + // Unpack the 256 total bits from the 10 uint32 words with a max of + // 26-bits per word. This could be done with a couple of for loops, + // but this unrolled version is a bit faster. Benchmarks show this is + // about 10 times faster than the variant which uses loops. + b[31] = byte(f.n[0] & eightBitsMask) + b[30] = byte((f.n[0] >> 8) & eightBitsMask) + b[29] = byte((f.n[0] >> 16) & eightBitsMask) + b[28] = byte((f.n[0]>>24)&twoBitsMask | (f.n[1]&sixBitsMask)<<2) + b[27] = byte((f.n[1] >> 6) & eightBitsMask) + b[26] = byte((f.n[1] >> 14) & eightBitsMask) + b[25] = byte((f.n[1]>>22)&fourBitsMask | (f.n[2]&fourBitsMask)<<4) + b[24] = byte((f.n[2] >> 4) & eightBitsMask) + b[23] = byte((f.n[2] >> 12) & eightBitsMask) + b[22] = byte((f.n[2]>>20)&sixBitsMask | (f.n[3]&twoBitsMask)<<6) + b[21] = byte((f.n[3] >> 2) & eightBitsMask) + b[20] = byte((f.n[3] >> 10) & eightBitsMask) + b[19] = byte((f.n[3] >> 18) & eightBitsMask) + b[18] = byte(f.n[4] & eightBitsMask) + b[17] = byte((f.n[4] >> 8) & eightBitsMask) + b[16] = byte((f.n[4] >> 16) & eightBitsMask) + b[15] = byte((f.n[4]>>24)&twoBitsMask | (f.n[5]&sixBitsMask)<<2) + b[14] = byte((f.n[5] >> 6) & eightBitsMask) + b[13] = byte((f.n[5] >> 14) & eightBitsMask) + b[12] = byte((f.n[5]>>22)&fourBitsMask | (f.n[6]&fourBitsMask)<<4) + b[11] = byte((f.n[6] >> 4) & eightBitsMask) + b[10] = byte((f.n[6] >> 12) & eightBitsMask) + b[9] = byte((f.n[6]>>20)&sixBitsMask | (f.n[7]&twoBitsMask)<<6) + b[8] = byte((f.n[7] >> 2) & eightBitsMask) + b[7] = byte((f.n[7] >> 10) & eightBitsMask) + b[6] = byte((f.n[7] >> 18) & eightBitsMask) + b[5] = byte(f.n[8] & eightBitsMask) + b[4] = byte((f.n[8] >> 8) & eightBitsMask) + b[3] = byte((f.n[8] >> 16) & eightBitsMask) + b[2] = byte((f.n[8]>>24)&twoBitsMask | (f.n[9]&sixBitsMask)<<2) + b[1] = byte((f.n[9] >> 6) & eightBitsMask) + b[0] = byte((f.n[9] >> 14) & eightBitsMask) +} + +// Bytes unpacks the field value to a 32-byte big-endian value. See PutBytes +// for a variant that allows the a buffer to be passed which can be useful to +// to cut down on the number of allocations by allowing the caller to reuse a +// buffer. +// +// The field value must be normalized for this function to return correct +// result. +func (f *fieldVal) Bytes() *[32]byte { + b := new([32]byte) + f.PutBytes(b) + return b +} + +// IsZero returns whether or not the field value is equal to zero. +func (f *fieldVal) IsZero() bool { + // The value can only be zero if no bits are set in any of the words. + // This is a constant time implementation. + bits := f.n[0] | f.n[1] | f.n[2] | f.n[3] | f.n[4] | + f.n[5] | f.n[6] | f.n[7] | f.n[8] | f.n[9] + + return bits == 0 +} + +// IsOdd returns whether or not the field value is an odd number. +// +// The field value must be normalized for this function to return correct +// result. +func (f *fieldVal) IsOdd() bool { + // Only odd numbers have the bottom bit set. + return f.n[0]&1 == 1 +} + +// Equals returns whether or not the two field values are the same. Both +// field values being compared must be normalized for this function to return +// the correct result. +func (f *fieldVal) Equals(val *fieldVal) bool { + // Xor only sets bits when they are different, so the two field values + // can only be the same if no bits are set after xoring each word. + // This is a constant time implementation. + bits := (f.n[0] ^ val.n[0]) | (f.n[1] ^ val.n[1]) | (f.n[2] ^ val.n[2]) | + (f.n[3] ^ val.n[3]) | (f.n[4] ^ val.n[4]) | (f.n[5] ^ val.n[5]) | + (f.n[6] ^ val.n[6]) | (f.n[7] ^ val.n[7]) | (f.n[8] ^ val.n[8]) | + (f.n[9] ^ val.n[9]) + + return bits == 0 +} + +// NegateVal negates the passed value and stores the result in f. The caller +// must provide the magnitude of the passed value for a correct result. +// +// The field value is returned to support chaining. This enables syntax like: +// f.NegateVal(f2).AddInt(1) so that f = -f2 + 1. +func (f *fieldVal) NegateVal(val *fieldVal, magnitude uint32) *fieldVal { + // Negation in the field is just the prime minus the value. However, + // in order to allow negation against a field value without having to + // normalize/reduce it first, multiply by the magnitude (that is how + // "far" away it is from the normalized value) to adjust. Also, since + // negating a value pushes it one more order of magnitude away from the + // normalized range, add 1 to compensate. + // + // For some intuition here, imagine you're performing mod 12 arithmetic + // (picture a clock) and you are negating the number 7. So you start at + // 12 (which is of course 0 under mod 12) and count backwards (left on + // the clock) 7 times to arrive at 5. Notice this is just 12-7 = 5. + // Now, assume you're starting with 19, which is a number that is + // already larger than the modulus and congruent to 7 (mod 12). When a + // value is already in the desired range, its magnitude is 1. Since 19 + // is an additional "step", its magnitude (mod 12) is 2. Since any + // multiple of the modulus is conguent to zero (mod m), the answer can + // be shortcut by simply mulplying the magnitude by the modulus and + // subtracting. Keeping with the example, this would be (2*12)-19 = 5. + f.n[0] = (magnitude+1)*fieldPrimeWordZero - val.n[0] + f.n[1] = (magnitude+1)*fieldPrimeWordOne - val.n[1] + f.n[2] = (magnitude+1)*fieldBaseMask - val.n[2] + f.n[3] = (magnitude+1)*fieldBaseMask - val.n[3] + f.n[4] = (magnitude+1)*fieldBaseMask - val.n[4] + f.n[5] = (magnitude+1)*fieldBaseMask - val.n[5] + f.n[6] = (magnitude+1)*fieldBaseMask - val.n[6] + f.n[7] = (magnitude+1)*fieldBaseMask - val.n[7] + f.n[8] = (magnitude+1)*fieldBaseMask - val.n[8] + f.n[9] = (magnitude+1)*fieldMSBMask - val.n[9] + + return f +} + +// Negate negates the field value. The existing field value is modified. The +// caller must provide the magnitude of the field value for a correct result. +// +// The field value is returned to support chaining. This enables syntax like: +// f.Negate().AddInt(1) so that f = -f + 1. +func (f *fieldVal) Negate(magnitude uint32) *fieldVal { + return f.NegateVal(f, magnitude) +} + +// AddInt adds the passed integer to the existing field value and stores the +// result in f. This is a convenience function since it is fairly common to +// perform some arithemetic with small native integers. +// +// The field value is returned to support chaining. This enables syntax like: +// f.AddInt(1).Add(f2) so that f = f + 1 + f2. +func (f *fieldVal) AddInt(ui uint) *fieldVal { + // Since the field representation intentionally provides overflow bits, + // it's ok to use carryless addition as the carry bit is safely part of + // the word and will be normalized out. + f.n[0] += uint32(ui) + + return f +} + +// Add adds the passed value to the existing field value and stores the result +// in f. +// +// The field value is returned to support chaining. This enables syntax like: +// f.Add(f2).AddInt(1) so that f = f + f2 + 1. +func (f *fieldVal) Add(val *fieldVal) *fieldVal { + // Since the field representation intentionally provides overflow bits, + // it's ok to use carryless addition as the carry bit is safely part of + // each word and will be normalized out. This could obviously be done + // in a loop, but the unrolled version is faster. + f.n[0] += val.n[0] + f.n[1] += val.n[1] + f.n[2] += val.n[2] + f.n[3] += val.n[3] + f.n[4] += val.n[4] + f.n[5] += val.n[5] + f.n[6] += val.n[6] + f.n[7] += val.n[7] + f.n[8] += val.n[8] + f.n[9] += val.n[9] + + return f +} + +// Add2 adds the passed two field values together and stores the result in f. +// +// The field value is returned to support chaining. This enables syntax like: +// f3.Add2(f, f2).AddInt(1) so that f3 = f + f2 + 1. +func (f *fieldVal) Add2(val *fieldVal, val2 *fieldVal) *fieldVal { + // Since the field representation intentionally provides overflow bits, + // it's ok to use carryless addition as the carry bit is safely part of + // each word and will be normalized out. This could obviously be done + // in a loop, but the unrolled version is faster. + f.n[0] = val.n[0] + val2.n[0] + f.n[1] = val.n[1] + val2.n[1] + f.n[2] = val.n[2] + val2.n[2] + f.n[3] = val.n[3] + val2.n[3] + f.n[4] = val.n[4] + val2.n[4] + f.n[5] = val.n[5] + val2.n[5] + f.n[6] = val.n[6] + val2.n[6] + f.n[7] = val.n[7] + val2.n[7] + f.n[8] = val.n[8] + val2.n[8] + f.n[9] = val.n[9] + val2.n[9] + + return f +} + +// MulInt multiplies the field value by the passed int and stores the result in +// f. Note that this function can overflow if multiplying the value by any of +// the individual words exceeds a max uint32. Therefore it is important that +// the caller ensures no overflows will occur before using this function. +// +// The field value is returned to support chaining. This enables syntax like: +// f.MulInt(2).Add(f2) so that f = 2 * f + f2. +func (f *fieldVal) MulInt(val uint) *fieldVal { + // Since each word of the field representation can hold up to + // fieldOverflowBits extra bits which will be normalized out, it's safe + // to multiply each word without using a larger type or carry + // propagation so long as the values won't overflow a uint32. This + // could obviously be done in a loop, but the unrolled version is + // faster. + ui := uint32(val) + f.n[0] *= ui + f.n[1] *= ui + f.n[2] *= ui + f.n[3] *= ui + f.n[4] *= ui + f.n[5] *= ui + f.n[6] *= ui + f.n[7] *= ui + f.n[8] *= ui + f.n[9] *= ui + + return f +} + +// Mul multiplies the passed value to the existing field value and stores the +// result in f. Note that this function can overflow if multiplying any +// of the individual words exceeds a max uint32. In practice, this means the +// magnitude of either value involved in the multiplication must be a max of +// 8. +// +// The field value is returned to support chaining. This enables syntax like: +// f.Mul(f2).AddInt(1) so that f = (f * f2) + 1. +func (f *fieldVal) Mul(val *fieldVal) *fieldVal { + return f.Mul2(f, val) +} + +// Mul2 multiplies the passed two field values together and stores the result +// result in f. Note that this function can overflow if multiplying any of +// the individual words exceeds a max uint32. In practice, this means the +// magnitude of either value involved in the multiplication must be a max of +// 8. +// +// The field value is returned to support chaining. This enables syntax like: +// f3.Mul2(f, f2).AddInt(1) so that f3 = (f * f2) + 1. +func (f *fieldVal) Mul2(val *fieldVal, val2 *fieldVal) *fieldVal { + // This could be done with a couple of for loops and an array to store + // the intermediate terms, but this unrolled version is significantly + // faster. + + // Terms for 2^(fieldBase*0). + m := uint64(val.n[0]) * uint64(val2.n[0]) + t0 := m & fieldBaseMask + + // Terms for 2^(fieldBase*1). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[1]) + + uint64(val.n[1])*uint64(val2.n[0]) + t1 := m & fieldBaseMask + + // Terms for 2^(fieldBase*2). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[2]) + + uint64(val.n[1])*uint64(val2.n[1]) + + uint64(val.n[2])*uint64(val2.n[0]) + t2 := m & fieldBaseMask + + // Terms for 2^(fieldBase*3). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[3]) + + uint64(val.n[1])*uint64(val2.n[2]) + + uint64(val.n[2])*uint64(val2.n[1]) + + uint64(val.n[3])*uint64(val2.n[0]) + t3 := m & fieldBaseMask + + // Terms for 2^(fieldBase*4). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[4]) + + uint64(val.n[1])*uint64(val2.n[3]) + + uint64(val.n[2])*uint64(val2.n[2]) + + uint64(val.n[3])*uint64(val2.n[1]) + + uint64(val.n[4])*uint64(val2.n[0]) + t4 := m & fieldBaseMask + + // Terms for 2^(fieldBase*5). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[5]) + + uint64(val.n[1])*uint64(val2.n[4]) + + uint64(val.n[2])*uint64(val2.n[3]) + + uint64(val.n[3])*uint64(val2.n[2]) + + uint64(val.n[4])*uint64(val2.n[1]) + + uint64(val.n[5])*uint64(val2.n[0]) + t5 := m & fieldBaseMask + + // Terms for 2^(fieldBase*6). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[6]) + + uint64(val.n[1])*uint64(val2.n[5]) + + uint64(val.n[2])*uint64(val2.n[4]) + + uint64(val.n[3])*uint64(val2.n[3]) + + uint64(val.n[4])*uint64(val2.n[2]) + + uint64(val.n[5])*uint64(val2.n[1]) + + uint64(val.n[6])*uint64(val2.n[0]) + t6 := m & fieldBaseMask + + // Terms for 2^(fieldBase*7). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[7]) + + uint64(val.n[1])*uint64(val2.n[6]) + + uint64(val.n[2])*uint64(val2.n[5]) + + uint64(val.n[3])*uint64(val2.n[4]) + + uint64(val.n[4])*uint64(val2.n[3]) + + uint64(val.n[5])*uint64(val2.n[2]) + + uint64(val.n[6])*uint64(val2.n[1]) + + uint64(val.n[7])*uint64(val2.n[0]) + t7 := m & fieldBaseMask + + // Terms for 2^(fieldBase*8). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[8]) + + uint64(val.n[1])*uint64(val2.n[7]) + + uint64(val.n[2])*uint64(val2.n[6]) + + uint64(val.n[3])*uint64(val2.n[5]) + + uint64(val.n[4])*uint64(val2.n[4]) + + uint64(val.n[5])*uint64(val2.n[3]) + + uint64(val.n[6])*uint64(val2.n[2]) + + uint64(val.n[7])*uint64(val2.n[1]) + + uint64(val.n[8])*uint64(val2.n[0]) + t8 := m & fieldBaseMask + + // Terms for 2^(fieldBase*9). + m = (m >> fieldBase) + + uint64(val.n[0])*uint64(val2.n[9]) + + uint64(val.n[1])*uint64(val2.n[8]) + + uint64(val.n[2])*uint64(val2.n[7]) + + uint64(val.n[3])*uint64(val2.n[6]) + + uint64(val.n[4])*uint64(val2.n[5]) + + uint64(val.n[5])*uint64(val2.n[4]) + + uint64(val.n[6])*uint64(val2.n[3]) + + uint64(val.n[7])*uint64(val2.n[2]) + + uint64(val.n[8])*uint64(val2.n[1]) + + uint64(val.n[9])*uint64(val2.n[0]) + t9 := m & fieldBaseMask + + // Terms for 2^(fieldBase*10). + m = (m >> fieldBase) + + uint64(val.n[1])*uint64(val2.n[9]) + + uint64(val.n[2])*uint64(val2.n[8]) + + uint64(val.n[3])*uint64(val2.n[7]) + + uint64(val.n[4])*uint64(val2.n[6]) + + uint64(val.n[5])*uint64(val2.n[5]) + + uint64(val.n[6])*uint64(val2.n[4]) + + uint64(val.n[7])*uint64(val2.n[3]) + + uint64(val.n[8])*uint64(val2.n[2]) + + uint64(val.n[9])*uint64(val2.n[1]) + t10 := m & fieldBaseMask + + // Terms for 2^(fieldBase*11). + m = (m >> fieldBase) + + uint64(val.n[2])*uint64(val2.n[9]) + + uint64(val.n[3])*uint64(val2.n[8]) + + uint64(val.n[4])*uint64(val2.n[7]) + + uint64(val.n[5])*uint64(val2.n[6]) + + uint64(val.n[6])*uint64(val2.n[5]) + + uint64(val.n[7])*uint64(val2.n[4]) + + uint64(val.n[8])*uint64(val2.n[3]) + + uint64(val.n[9])*uint64(val2.n[2]) + t11 := m & fieldBaseMask + + // Terms for 2^(fieldBase*12). + m = (m >> fieldBase) + + uint64(val.n[3])*uint64(val2.n[9]) + + uint64(val.n[4])*uint64(val2.n[8]) + + uint64(val.n[5])*uint64(val2.n[7]) + + uint64(val.n[6])*uint64(val2.n[6]) + + uint64(val.n[7])*uint64(val2.n[5]) + + uint64(val.n[8])*uint64(val2.n[4]) + + uint64(val.n[9])*uint64(val2.n[3]) + t12 := m & fieldBaseMask + + // Terms for 2^(fieldBase*13). + m = (m >> fieldBase) + + uint64(val.n[4])*uint64(val2.n[9]) + + uint64(val.n[5])*uint64(val2.n[8]) + + uint64(val.n[6])*uint64(val2.n[7]) + + uint64(val.n[7])*uint64(val2.n[6]) + + uint64(val.n[8])*uint64(val2.n[5]) + + uint64(val.n[9])*uint64(val2.n[4]) + t13 := m & fieldBaseMask + + // Terms for 2^(fieldBase*14). + m = (m >> fieldBase) + + uint64(val.n[5])*uint64(val2.n[9]) + + uint64(val.n[6])*uint64(val2.n[8]) + + uint64(val.n[7])*uint64(val2.n[7]) + + uint64(val.n[8])*uint64(val2.n[6]) + + uint64(val.n[9])*uint64(val2.n[5]) + t14 := m & fieldBaseMask + + // Terms for 2^(fieldBase*15). + m = (m >> fieldBase) + + uint64(val.n[6])*uint64(val2.n[9]) + + uint64(val.n[7])*uint64(val2.n[8]) + + uint64(val.n[8])*uint64(val2.n[7]) + + uint64(val.n[9])*uint64(val2.n[6]) + t15 := m & fieldBaseMask + + // Terms for 2^(fieldBase*16). + m = (m >> fieldBase) + + uint64(val.n[7])*uint64(val2.n[9]) + + uint64(val.n[8])*uint64(val2.n[8]) + + uint64(val.n[9])*uint64(val2.n[7]) + t16 := m & fieldBaseMask + + // Terms for 2^(fieldBase*17). + m = (m >> fieldBase) + + uint64(val.n[8])*uint64(val2.n[9]) + + uint64(val.n[9])*uint64(val2.n[8]) + t17 := m & fieldBaseMask + + // Terms for 2^(fieldBase*18). + m = (m >> fieldBase) + uint64(val.n[9])*uint64(val2.n[9]) + t18 := m & fieldBaseMask + + // What's left is for 2^(fieldBase*19). + t19 := m >> fieldBase + + // At this point, all of the terms are grouped into their respective + // base. + // + // Per [HAC] section 14.3.4: Reduction method of moduli of special form, + // when the modulus is of the special form m = b^t - c, highly efficient + // reduction can be achieved per the provided algorithm. + // + // The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits + // this criteria. + // + // 4294968273 in field representation (base 2^26) is: + // n[0] = 977 + // n[1] = 64 + // That is to say (2^26 * 64) + 977 = 4294968273 + // + // Since each word is in base 26, the upper terms (t10 and up) start + // at 260 bits (versus the final desired range of 256 bits), so the + // field representation of 'c' from above needs to be adjusted for the + // extra 4 bits by multiplying it by 2^4 = 16. 4294968273 * 16 = + // 68719492368. Thus, the adjusted field representation of 'c' is: + // n[0] = 977 * 16 = 15632 + // n[1] = 64 * 16 = 1024 + // That is to say (2^26 * 1024) + 15632 = 68719492368 + // + // To reduce the final term, t19, the entire 'c' value is needed instead + // of only n[0] because there are no more terms left to handle n[1]. + // This means there might be some magnitude left in the upper bits that + // is handled below. + m = t0 + t10*15632 + t0 = m & fieldBaseMask + m = (m >> fieldBase) + t1 + t10*1024 + t11*15632 + t1 = m & fieldBaseMask + m = (m >> fieldBase) + t2 + t11*1024 + t12*15632 + t2 = m & fieldBaseMask + m = (m >> fieldBase) + t3 + t12*1024 + t13*15632 + t3 = m & fieldBaseMask + m = (m >> fieldBase) + t4 + t13*1024 + t14*15632 + t4 = m & fieldBaseMask + m = (m >> fieldBase) + t5 + t14*1024 + t15*15632 + t5 = m & fieldBaseMask + m = (m >> fieldBase) + t6 + t15*1024 + t16*15632 + t6 = m & fieldBaseMask + m = (m >> fieldBase) + t7 + t16*1024 + t17*15632 + t7 = m & fieldBaseMask + m = (m >> fieldBase) + t8 + t17*1024 + t18*15632 + t8 = m & fieldBaseMask + m = (m >> fieldBase) + t9 + t18*1024 + t19*68719492368 + t9 = m & fieldMSBMask + m = m >> fieldMSBBits + + // At this point, if the magnitude is greater than 0, the overall value + // is greater than the max possible 256-bit value. In particular, it is + // "how many times larger" than the max value it is. + // + // The algorithm presented in [HAC] section 14.3.4 repeats until the + // quotient is zero. However, due to the above, we already know at + // least how many times we would need to repeat as it's the value + // currently in m. Thus we can simply multiply the magnitude by the + // field representation of the prime and do a single iteration. Notice + // that nothing will be changed when the magnitude is zero, so we could + // skip this in that case, however always running regardless allows it + // to run in constant time. The final result will be in the range + // 0 <= result <= prime + (2^64 - c), so it is guaranteed to have a + // magnitude of 1, but it is denormalized. + d := t0 + m*977 + f.n[0] = uint32(d & fieldBaseMask) + d = (d >> fieldBase) + t1 + m*64 + f.n[1] = uint32(d & fieldBaseMask) + f.n[2] = uint32((d >> fieldBase) + t2) + f.n[3] = uint32(t3) + f.n[4] = uint32(t4) + f.n[5] = uint32(t5) + f.n[6] = uint32(t6) + f.n[7] = uint32(t7) + f.n[8] = uint32(t8) + f.n[9] = uint32(t9) + + return f +} + +// Square squares the field value. The existing field value is modified. Note +// that this function can overflow if multiplying any of the individual words +// exceeds a max uint32. In practice, this means the magnitude of the field +// must be a max of 8 to prevent overflow. +// +// The field value is returned to support chaining. This enables syntax like: +// f.Square().Mul(f2) so that f = f^2 * f2. +func (f *fieldVal) Square() *fieldVal { + return f.SquareVal(f) +} + +// SquareVal squares the passed value and stores the result in f. Note that +// this function can overflow if multiplying any of the individual words +// exceeds a max uint32. In practice, this means the magnitude of the field +// being squred must be a max of 8 to prevent overflow. +// +// The field value is returned to support chaining. This enables syntax like: +// f3.SquareVal(f).Mul(f) so that f3 = f^2 * f = f^3. +func (f *fieldVal) SquareVal(val *fieldVal) *fieldVal { + // This could be done with a couple of for loops and an array to store + // the intermediate terms, but this unrolled version is significantly + // faster. + + // Terms for 2^(fieldBase*0). + m := uint64(val.n[0]) * uint64(val.n[0]) + t0 := m & fieldBaseMask + + // Terms for 2^(fieldBase*1). + m = (m >> fieldBase) + 2*uint64(val.n[0])*uint64(val.n[1]) + t1 := m & fieldBaseMask + + // Terms for 2^(fieldBase*2). + m = (m >> fieldBase) + + 2*uint64(val.n[0])*uint64(val.n[2]) + + uint64(val.n[1])*uint64(val.n[1]) + t2 := m & fieldBaseMask + + // Terms for 2^(fieldBase*3). + m = (m >> fieldBase) + + 2*uint64(val.n[0])*uint64(val.n[3]) + + 2*uint64(val.n[1])*uint64(val.n[2]) + t3 := m & fieldBaseMask + + // Terms for 2^(fieldBase*4). + m = (m >> fieldBase) + + 2*uint64(val.n[0])*uint64(val.n[4]) + + 2*uint64(val.n[1])*uint64(val.n[3]) + + uint64(val.n[2])*uint64(val.n[2]) + t4 := m & fieldBaseMask + + // Terms for 2^(fieldBase*5). + m = (m >> fieldBase) + + 2*uint64(val.n[0])*uint64(val.n[5]) + + 2*uint64(val.n[1])*uint64(val.n[4]) + + 2*uint64(val.n[2])*uint64(val.n[3]) + t5 := m & fieldBaseMask + + // Terms for 2^(fieldBase*6). + m = (m >> fieldBase) + + 2*uint64(val.n[0])*uint64(val.n[6]) + + 2*uint64(val.n[1])*uint64(val.n[5]) + + 2*uint64(val.n[2])*uint64(val.n[4]) + + uint64(val.n[3])*uint64(val.n[3]) + t6 := m & fieldBaseMask + + // Terms for 2^(fieldBase*7). + m = (m >> fieldBase) + + 2*uint64(val.n[0])*uint64(val.n[7]) + + 2*uint64(val.n[1])*uint64(val.n[6]) + + 2*uint64(val.n[2])*uint64(val.n[5]) + + 2*uint64(val.n[3])*uint64(val.n[4]) + t7 := m & fieldBaseMask + + // Terms for 2^(fieldBase*8). + m = (m >> fieldBase) + + 2*uint64(val.n[0])*uint64(val.n[8]) + + 2*uint64(val.n[1])*uint64(val.n[7]) + + 2*uint64(val.n[2])*uint64(val.n[6]) + + 2*uint64(val.n[3])*uint64(val.n[5]) + + uint64(val.n[4])*uint64(val.n[4]) + t8 := m & fieldBaseMask + + // Terms for 2^(fieldBase*9). + m = (m >> fieldBase) + + 2*uint64(val.n[0])*uint64(val.n[9]) + + 2*uint64(val.n[1])*uint64(val.n[8]) + + 2*uint64(val.n[2])*uint64(val.n[7]) + + 2*uint64(val.n[3])*uint64(val.n[6]) + + 2*uint64(val.n[4])*uint64(val.n[5]) + t9 := m & fieldBaseMask + + // Terms for 2^(fieldBase*10). + m = (m >> fieldBase) + + 2*uint64(val.n[1])*uint64(val.n[9]) + + 2*uint64(val.n[2])*uint64(val.n[8]) + + 2*uint64(val.n[3])*uint64(val.n[7]) + + 2*uint64(val.n[4])*uint64(val.n[6]) + + uint64(val.n[5])*uint64(val.n[5]) + t10 := m & fieldBaseMask + + // Terms for 2^(fieldBase*11). + m = (m >> fieldBase) + + 2*uint64(val.n[2])*uint64(val.n[9]) + + 2*uint64(val.n[3])*uint64(val.n[8]) + + 2*uint64(val.n[4])*uint64(val.n[7]) + + 2*uint64(val.n[5])*uint64(val.n[6]) + t11 := m & fieldBaseMask + + // Terms for 2^(fieldBase*12). + m = (m >> fieldBase) + + 2*uint64(val.n[3])*uint64(val.n[9]) + + 2*uint64(val.n[4])*uint64(val.n[8]) + + 2*uint64(val.n[5])*uint64(val.n[7]) + + uint64(val.n[6])*uint64(val.n[6]) + t12 := m & fieldBaseMask + + // Terms for 2^(fieldBase*13). + m = (m >> fieldBase) + + 2*uint64(val.n[4])*uint64(val.n[9]) + + 2*uint64(val.n[5])*uint64(val.n[8]) + + 2*uint64(val.n[6])*uint64(val.n[7]) + t13 := m & fieldBaseMask + + // Terms for 2^(fieldBase*14). + m = (m >> fieldBase) + + 2*uint64(val.n[5])*uint64(val.n[9]) + + 2*uint64(val.n[6])*uint64(val.n[8]) + + uint64(val.n[7])*uint64(val.n[7]) + t14 := m & fieldBaseMask + + // Terms for 2^(fieldBase*15). + m = (m >> fieldBase) + + 2*uint64(val.n[6])*uint64(val.n[9]) + + 2*uint64(val.n[7])*uint64(val.n[8]) + t15 := m & fieldBaseMask + + // Terms for 2^(fieldBase*16). + m = (m >> fieldBase) + + 2*uint64(val.n[7])*uint64(val.n[9]) + + uint64(val.n[8])*uint64(val.n[8]) + t16 := m & fieldBaseMask + + // Terms for 2^(fieldBase*17). + m = (m >> fieldBase) + 2*uint64(val.n[8])*uint64(val.n[9]) + t17 := m & fieldBaseMask + + // Terms for 2^(fieldBase*18). + m = (m >> fieldBase) + uint64(val.n[9])*uint64(val.n[9]) + t18 := m & fieldBaseMask + + // What's left is for 2^(fieldBase*19). + t19 := m >> fieldBase + + // At this point, all of the terms are grouped into their respective + // base. + // + // Per [HAC] section 14.3.4: Reduction method of moduli of special form, + // when the modulus is of the special form m = b^t - c, highly efficient + // reduction can be achieved per the provided algorithm. + // + // The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits + // this criteria. + // + // 4294968273 in field representation (base 2^26) is: + // n[0] = 977 + // n[1] = 64 + // That is to say (2^26 * 64) + 977 = 4294968273 + // + // Since each word is in base 26, the upper terms (t10 and up) start + // at 260 bits (versus the final desired range of 256 bits), so the + // field representation of 'c' from above needs to be adjusted for the + // extra 4 bits by multiplying it by 2^4 = 16. 4294968273 * 16 = + // 68719492368. Thus, the adjusted field representation of 'c' is: + // n[0] = 977 * 16 = 15632 + // n[1] = 64 * 16 = 1024 + // That is to say (2^26 * 1024) + 15632 = 68719492368 + // + // To reduce the final term, t19, the entire 'c' value is needed instead + // of only n[0] because there are no more terms left to handle n[1]. + // This means there might be some magnitude left in the upper bits that + // is handled below. + m = t0 + t10*15632 + t0 = m & fieldBaseMask + m = (m >> fieldBase) + t1 + t10*1024 + t11*15632 + t1 = m & fieldBaseMask + m = (m >> fieldBase) + t2 + t11*1024 + t12*15632 + t2 = m & fieldBaseMask + m = (m >> fieldBase) + t3 + t12*1024 + t13*15632 + t3 = m & fieldBaseMask + m = (m >> fieldBase) + t4 + t13*1024 + t14*15632 + t4 = m & fieldBaseMask + m = (m >> fieldBase) + t5 + t14*1024 + t15*15632 + t5 = m & fieldBaseMask + m = (m >> fieldBase) + t6 + t15*1024 + t16*15632 + t6 = m & fieldBaseMask + m = (m >> fieldBase) + t7 + t16*1024 + t17*15632 + t7 = m & fieldBaseMask + m = (m >> fieldBase) + t8 + t17*1024 + t18*15632 + t8 = m & fieldBaseMask + m = (m >> fieldBase) + t9 + t18*1024 + t19*68719492368 + t9 = m & fieldMSBMask + m = m >> fieldMSBBits + + // At this point, if the magnitude is greater than 0, the overall value + // is greater than the max possible 256-bit value. In particular, it is + // "how many times larger" than the max value it is. + // + // The algorithm presented in [HAC] section 14.3.4 repeats until the + // quotient is zero. However, due to the above, we already know at + // least how many times we would need to repeat as it's the value + // currently in m. Thus we can simply multiply the magnitude by the + // field representation of the prime and do a single iteration. Notice + // that nothing will be changed when the magnitude is zero, so we could + // skip this in that case, however always running regardless allows it + // to run in constant time. The final result will be in the range + // 0 <= result <= prime + (2^64 - c), so it is guaranteed to have a + // magnitude of 1, but it is denormalized. + n := t0 + m*977 + f.n[0] = uint32(n & fieldBaseMask) + n = (n >> fieldBase) + t1 + m*64 + f.n[1] = uint32(n & fieldBaseMask) + f.n[2] = uint32((n >> fieldBase) + t2) + f.n[3] = uint32(t3) + f.n[4] = uint32(t4) + f.n[5] = uint32(t5) + f.n[6] = uint32(t6) + f.n[7] = uint32(t7) + f.n[8] = uint32(t8) + f.n[9] = uint32(t9) + + return f +} + +// Inverse finds the modular multiplicative inverse of the field value. The +// existing field value is modified. +// +// The field value is returned to support chaining. This enables syntax like: +// f.Inverse().Mul(f2) so that f = f^-1 * f2. +func (f *fieldVal) Inverse() *fieldVal { + // Fermat's little theorem states that for a nonzero number a and prime + // prime p, a^(p-1) = 1 (mod p). Since the multipliciative inverse is + // a*b = 1 (mod p), it follows that b = a*a^(p-2) = a^(p-1) = 1 (mod p). + // Thus, a^(p-2) is the multiplicative inverse. + // + // In order to efficiently compute a^(p-2), p-2 needs to be split into + // a sequence of squares and multipications that minimizes the number of + // multiplications needed (since they are more costly than squarings). + // Intermediate results are saved and reused as well. + // + // The secp256k1 prime - 2 is 2^256 - 4294968275. + // + // This has a cost of 258 field squarings and 33 field multiplications. + var a2, a3, a4, a10, a11, a21, a42, a45, a63, a1019, a1023 fieldVal + a2.SquareVal(f) + a3.Mul2(&a2, f) + a4.SquareVal(&a2) + a10.SquareVal(&a4).Mul(&a2) + a11.Mul2(&a10, f) + a21.Mul2(&a10, &a11) + a42.SquareVal(&a21) + a45.Mul2(&a42, &a3) + a63.Mul2(&a42, &a21) + a1019.SquareVal(&a63).Square().Square().Square().Mul(&a11) + a1023.Mul2(&a1019, &a4) + f.Set(&a63) // f = a^(2^6 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^11 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^16 - 1024) + f.Mul(&a1023) // f = a^(2^16 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^21 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^26 - 1024) + f.Mul(&a1023) // f = a^(2^26 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^31 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^36 - 1024) + f.Mul(&a1023) // f = a^(2^36 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^41 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^46 - 1024) + f.Mul(&a1023) // f = a^(2^46 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^51 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^56 - 1024) + f.Mul(&a1023) // f = a^(2^56 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^61 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^66 - 1024) + f.Mul(&a1023) // f = a^(2^66 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^71 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^76 - 1024) + f.Mul(&a1023) // f = a^(2^76 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^81 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^86 - 1024) + f.Mul(&a1023) // f = a^(2^86 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^91 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^96 - 1024) + f.Mul(&a1023) // f = a^(2^96 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^101 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^106 - 1024) + f.Mul(&a1023) // f = a^(2^106 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^111 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^116 - 1024) + f.Mul(&a1023) // f = a^(2^116 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^121 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^126 - 1024) + f.Mul(&a1023) // f = a^(2^126 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^131 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^136 - 1024) + f.Mul(&a1023) // f = a^(2^136 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^141 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^146 - 1024) + f.Mul(&a1023) // f = a^(2^146 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^151 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^156 - 1024) + f.Mul(&a1023) // f = a^(2^156 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^161 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^166 - 1024) + f.Mul(&a1023) // f = a^(2^166 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^171 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^176 - 1024) + f.Mul(&a1023) // f = a^(2^176 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^181 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^186 - 1024) + f.Mul(&a1023) // f = a^(2^186 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^191 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^196 - 1024) + f.Mul(&a1023) // f = a^(2^196 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^201 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^206 - 1024) + f.Mul(&a1023) // f = a^(2^206 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^211 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^216 - 1024) + f.Mul(&a1023) // f = a^(2^216 - 1) + f.Square().Square().Square().Square().Square() // f = a^(2^221 - 32) + f.Square().Square().Square().Square().Square() // f = a^(2^226 - 1024) + f.Mul(&a1019) // f = a^(2^226 - 5) + f.Square().Square().Square().Square().Square() // f = a^(2^231 - 160) + f.Square().Square().Square().Square().Square() // f = a^(2^236 - 5120) + f.Mul(&a1023) // f = a^(2^236 - 4097) + f.Square().Square().Square().Square().Square() // f = a^(2^241 - 131104) + f.Square().Square().Square().Square().Square() // f = a^(2^246 - 4195328) + f.Mul(&a1023) // f = a^(2^246 - 4194305) + f.Square().Square().Square().Square().Square() // f = a^(2^251 - 134217760) + f.Square().Square().Square().Square().Square() // f = a^(2^256 - 4294968320) + return f.Mul(&a45) // f = a^(2^256 - 4294968275) = a^(p-2) +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/gensecp256k1.go b/vendor/github.com/btcsuite/btcd/btcec/gensecp256k1.go new file mode 100644 index 00000000..1928702d --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/gensecp256k1.go @@ -0,0 +1,203 @@ +// Copyright (c) 2014-2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// This file is ignored during the regular build due to the following build tag. +// This build tag is set during go generate. +// +build gensecp256k1 + +package btcec + +// References: +// [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone) + +import ( + "encoding/binary" + "math/big" +) + +// secp256k1BytePoints are dummy points used so the code which generates the +// real values can compile. +var secp256k1BytePoints = "" + +// getDoublingPoints returns all the possible G^(2^i) for i in +// 0..n-1 where n is the curve's bit size (256 in the case of secp256k1) +// the coordinates are recorded as Jacobian coordinates. +func (curve *KoblitzCurve) getDoublingPoints() [][3]fieldVal { + doublingPoints := make([][3]fieldVal, curve.BitSize) + + // initialize px, py, pz to the Jacobian coordinates for the base point + px, py := curve.bigAffineToField(curve.Gx, curve.Gy) + pz := new(fieldVal).SetInt(1) + for i := 0; i < curve.BitSize; i++ { + doublingPoints[i] = [3]fieldVal{*px, *py, *pz} + // P = 2*P + curve.doubleJacobian(px, py, pz, px, py, pz) + } + return doublingPoints +} + +// SerializedBytePoints returns a serialized byte slice which contains all of +// the possible points per 8-bit window. This is used to when generating +// secp256k1.go. +func (curve *KoblitzCurve) SerializedBytePoints() []byte { + doublingPoints := curve.getDoublingPoints() + + // Segregate the bits into byte-sized windows + serialized := make([]byte, curve.byteSize*256*3*10*4) + offset := 0 + for byteNum := 0; byteNum < curve.byteSize; byteNum++ { + // Grab the 8 bits that make up this byte from doublingPoints. + startingBit := 8 * (curve.byteSize - byteNum - 1) + computingPoints := doublingPoints[startingBit : startingBit+8] + + // Compute all points in this window and serialize them. + for i := 0; i < 256; i++ { + px, py, pz := new(fieldVal), new(fieldVal), new(fieldVal) + for j := 0; j < 8; j++ { + if i>>uint(j)&1 == 1 { + curve.addJacobian(px, py, pz, &computingPoints[j][0], + &computingPoints[j][1], &computingPoints[j][2], px, py, pz) + } + } + for i := 0; i < 10; i++ { + binary.LittleEndian.PutUint32(serialized[offset:], px.n[i]) + offset += 4 + } + for i := 0; i < 10; i++ { + binary.LittleEndian.PutUint32(serialized[offset:], py.n[i]) + offset += 4 + } + for i := 0; i < 10; i++ { + binary.LittleEndian.PutUint32(serialized[offset:], pz.n[i]) + offset += 4 + } + } + } + + return serialized +} + +// sqrt returns the square root of the provided big integer using Newton's +// method. It's only compiled and used during generation of pre-computed +// values, so speed is not a huge concern. +func sqrt(n *big.Int) *big.Int { + // Initial guess = 2^(log_2(n)/2) + guess := big.NewInt(2) + guess.Exp(guess, big.NewInt(int64(n.BitLen()/2)), nil) + + // Now refine using Newton's method. + big2 := big.NewInt(2) + prevGuess := big.NewInt(0) + for { + prevGuess.Set(guess) + guess.Add(guess, new(big.Int).Div(n, guess)) + guess.Div(guess, big2) + if guess.Cmp(prevGuess) == 0 { + break + } + } + return guess +} + +// EndomorphismVectors runs the first 3 steps of algorithm 3.74 from [GECC] to +// generate the linearly independent vectors needed to generate a balanced +// length-two representation of a multiplier such that k = k1 + k2λ (mod N) and +// returns them. Since the values will always be the same given the fact that N +// and λ are fixed, the final results can be accelerated by storing the +// precomputed values with the curve. +func (curve *KoblitzCurve) EndomorphismVectors() (a1, b1, a2, b2 *big.Int) { + bigMinus1 := big.NewInt(-1) + + // This section uses an extended Euclidean algorithm to generate a + // sequence of equations: + // s[i] * N + t[i] * λ = r[i] + + nSqrt := sqrt(curve.N) + u, v := new(big.Int).Set(curve.N), new(big.Int).Set(curve.lambda) + x1, y1 := big.NewInt(1), big.NewInt(0) + x2, y2 := big.NewInt(0), big.NewInt(1) + q, r := new(big.Int), new(big.Int) + qu, qx1, qy1 := new(big.Int), new(big.Int), new(big.Int) + s, t := new(big.Int), new(big.Int) + ri, ti := new(big.Int), new(big.Int) + a1, b1, a2, b2 = new(big.Int), new(big.Int), new(big.Int), new(big.Int) + found, oneMore := false, false + for u.Sign() != 0 { + // q = v/u + q.Div(v, u) + + // r = v - q*u + qu.Mul(q, u) + r.Sub(v, qu) + + // s = x2 - q*x1 + qx1.Mul(q, x1) + s.Sub(x2, qx1) + + // t = y2 - q*y1 + qy1.Mul(q, y1) + t.Sub(y2, qy1) + + // v = u, u = r, x2 = x1, x1 = s, y2 = y1, y1 = t + v.Set(u) + u.Set(r) + x2.Set(x1) + x1.Set(s) + y2.Set(y1) + y1.Set(t) + + // As soon as the remainder is less than the sqrt of n, the + // values of a1 and b1 are known. + if !found && r.Cmp(nSqrt) < 0 { + // When this condition executes ri and ti represent the + // r[i] and t[i] values such that i is the greatest + // index for which r >= sqrt(n). Meanwhile, the current + // r and t values are r[i+1] and t[i+1], respectively. + + // a1 = r[i+1], b1 = -t[i+1] + a1.Set(r) + b1.Mul(t, bigMinus1) + found = true + oneMore = true + + // Skip to the next iteration so ri and ti are not + // modified. + continue + + } else if oneMore { + // When this condition executes ri and ti still + // represent the r[i] and t[i] values while the current + // r and t are r[i+2] and t[i+2], respectively. + + // sum1 = r[i]^2 + t[i]^2 + rSquared := new(big.Int).Mul(ri, ri) + tSquared := new(big.Int).Mul(ti, ti) + sum1 := new(big.Int).Add(rSquared, tSquared) + + // sum2 = r[i+2]^2 + t[i+2]^2 + r2Squared := new(big.Int).Mul(r, r) + t2Squared := new(big.Int).Mul(t, t) + sum2 := new(big.Int).Add(r2Squared, t2Squared) + + // if (r[i]^2 + t[i]^2) <= (r[i+2]^2 + t[i+2]^2) + if sum1.Cmp(sum2) <= 0 { + // a2 = r[i], b2 = -t[i] + a2.Set(ri) + b2.Mul(ti, bigMinus1) + } else { + // a2 = r[i+2], b2 = -t[i+2] + a2.Set(r) + b2.Mul(t, bigMinus1) + } + + // All done. + break + } + + ri.Set(r) + ti.Set(t) + } + + return a1, b1, a2, b2 +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/precompute.go b/vendor/github.com/btcsuite/btcd/btcec/precompute.go new file mode 100644 index 00000000..034cd553 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/precompute.go @@ -0,0 +1,67 @@ +// Copyright 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +import ( + "compress/zlib" + "encoding/base64" + "encoding/binary" + "io/ioutil" + "strings" +) + +//go:generate go run -tags gensecp256k1 genprecomps.go + +// loadS256BytePoints decompresses and deserializes the pre-computed byte points +// used to accelerate scalar base multiplication for the secp256k1 curve. This +// approach is used since it allows the compile to use significantly less ram +// and be performed much faster than it is with hard-coding the final in-memory +// data structure. At the same time, it is quite fast to generate the in-memory +// data structure at init time with this approach versus computing the table. +func loadS256BytePoints() error { + // There will be no byte points to load when generating them. + bp := secp256k1BytePoints + if len(bp) == 0 { + return nil + } + + // Decompress the pre-computed table used to accelerate scalar base + // multiplication. + decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(bp)) + r, err := zlib.NewReader(decoder) + if err != nil { + return err + } + serialized, err := ioutil.ReadAll(r) + if err != nil { + return err + } + + // Deserialize the precomputed byte points and set the curve to them. + offset := 0 + var bytePoints [32][256][3]fieldVal + for byteNum := 0; byteNum < 32; byteNum++ { + // All points in this window. + for i := 0; i < 256; i++ { + px := &bytePoints[byteNum][i][0] + py := &bytePoints[byteNum][i][1] + pz := &bytePoints[byteNum][i][2] + for i := 0; i < 10; i++ { + px.n[i] = binary.LittleEndian.Uint32(serialized[offset:]) + offset += 4 + } + for i := 0; i < 10; i++ { + py.n[i] = binary.LittleEndian.Uint32(serialized[offset:]) + offset += 4 + } + for i := 0; i < 10; i++ { + pz.n[i] = binary.LittleEndian.Uint32(serialized[offset:]) + offset += 4 + } + } + } + secp256k1.bytePoints = &bytePoints + return nil +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/privkey.go b/vendor/github.com/btcsuite/btcd/btcec/privkey.go new file mode 100644 index 00000000..676a8c3f --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/privkey.go @@ -0,0 +1,73 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "math/big" +) + +// PrivateKey wraps an ecdsa.PrivateKey as a convenience mainly for signing +// things with the the private key without having to directly import the ecdsa +// package. +type PrivateKey ecdsa.PrivateKey + +// PrivKeyFromBytes returns a private and public key for `curve' based on the +// private key passed as an argument as a byte slice. +func PrivKeyFromBytes(curve elliptic.Curve, pk []byte) (*PrivateKey, + *PublicKey) { + x, y := curve.ScalarBaseMult(pk) + + priv := &ecdsa.PrivateKey{ + PublicKey: ecdsa.PublicKey{ + Curve: curve, + X: x, + Y: y, + }, + D: new(big.Int).SetBytes(pk), + } + + return (*PrivateKey)(priv), (*PublicKey)(&priv.PublicKey) +} + +// NewPrivateKey is a wrapper for ecdsa.GenerateKey that returns a PrivateKey +// instead of the normal ecdsa.PrivateKey. +func NewPrivateKey(curve elliptic.Curve) (*PrivateKey, error) { + key, err := ecdsa.GenerateKey(curve, rand.Reader) + if err != nil { + return nil, err + } + return (*PrivateKey)(key), nil +} + +// PubKey returns the PublicKey corresponding to this private key. +func (p *PrivateKey) PubKey() *PublicKey { + return (*PublicKey)(&p.PublicKey) +} + +// ToECDSA returns the private key as a *ecdsa.PrivateKey. +func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey { + return (*ecdsa.PrivateKey)(p) +} + +// Sign generates an ECDSA signature for the provided hash (which should be the result +// of hashing a larger message) using the private key. Produced signature +// is deterministic (same message and same key yield the same signature) and canonical +// in accordance with RFC6979 and BIP0062. +func (p *PrivateKey) Sign(hash []byte) (*Signature, error) { + return signRFC6979(p, hash) +} + +// PrivKeyBytesLen defines the length in bytes of a serialized private key. +const PrivKeyBytesLen = 32 + +// Serialize returns the private key number d as a big-endian binary-encoded +// number, padded to a length of 32 bytes. +func (p *PrivateKey) Serialize() []byte { + b := make([]byte, 0, PrivKeyBytesLen) + return paddedAppend(PrivKeyBytesLen, b, p.ToECDSA().D.Bytes()) +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/pubkey.go b/vendor/github.com/btcsuite/btcd/btcec/pubkey.go new file mode 100644 index 00000000..f145414e --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/pubkey.go @@ -0,0 +1,172 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +import ( + "crypto/ecdsa" + "errors" + "fmt" + "math/big" +) + +// These constants define the lengths of serialized public keys. +const ( + PubKeyBytesLenCompressed = 33 + PubKeyBytesLenUncompressed = 65 + PubKeyBytesLenHybrid = 65 +) + +func isOdd(a *big.Int) bool { + return a.Bit(0) == 1 +} + +// decompressPoint decompresses a point on the given curve given the X point and +// the solution to use. +func decompressPoint(curve *KoblitzCurve, x *big.Int, ybit bool) (*big.Int, error) { + // TODO: This will probably only work for secp256k1 due to + // optimizations. + + // Y = +-sqrt(x^3 + B) + x3 := new(big.Int).Mul(x, x) + x3.Mul(x3, x) + x3.Add(x3, curve.Params().B) + + // now calculate sqrt mod p of x2 + B + // This code used to do a full sqrt based on tonelli/shanks, + // but this was replaced by the algorithms referenced in + // https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294 + y := new(big.Int).Exp(x3, curve.QPlus1Div4(), curve.Params().P) + + if ybit != isOdd(y) { + y.Sub(curve.Params().P, y) + } + if ybit != isOdd(y) { + return nil, fmt.Errorf("ybit doesn't match oddness") + } + return y, nil +} + +const ( + pubkeyCompressed byte = 0x2 // y_bit + x coord + pubkeyUncompressed byte = 0x4 // x coord + y coord + pubkeyHybrid byte = 0x6 // y_bit + x coord + y coord +) + +// ParsePubKey parses a public key for a koblitz curve from a bytestring into a +// ecdsa.Publickey, verifying that it is valid. It supports compressed, +// uncompressed and hybrid signature formats. +func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err error) { + pubkey := PublicKey{} + pubkey.Curve = curve + + if len(pubKeyStr) == 0 { + return nil, errors.New("pubkey string is empty") + } + + format := pubKeyStr[0] + ybit := (format & 0x1) == 0x1 + format &= ^byte(0x1) + + switch len(pubKeyStr) { + case PubKeyBytesLenUncompressed: + if format != pubkeyUncompressed && format != pubkeyHybrid { + return nil, fmt.Errorf("invalid magic in pubkey str: "+ + "%d", pubKeyStr[0]) + } + + pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33]) + pubkey.Y = new(big.Int).SetBytes(pubKeyStr[33:]) + // hybrid keys have extra information, make use of it. + if format == pubkeyHybrid && ybit != isOdd(pubkey.Y) { + return nil, fmt.Errorf("ybit doesn't match oddness") + } + case PubKeyBytesLenCompressed: + // format is 0x2 | solution, + // solution determines which solution of the curve we use. + /// y^2 = x^3 + Curve.B + if format != pubkeyCompressed { + return nil, fmt.Errorf("invalid magic in compressed "+ + "pubkey string: %d", pubKeyStr[0]) + } + pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33]) + pubkey.Y, err = decompressPoint(curve, pubkey.X, ybit) + if err != nil { + return nil, err + } + default: // wrong! + return nil, fmt.Errorf("invalid pub key length %d", + len(pubKeyStr)) + } + + if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 { + return nil, fmt.Errorf("pubkey X parameter is >= to P") + } + if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 { + return nil, fmt.Errorf("pubkey Y parameter is >= to P") + } + if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) { + return nil, fmt.Errorf("pubkey isn't on secp256k1 curve") + } + return &pubkey, nil +} + +// PublicKey is an ecdsa.PublicKey with additional functions to +// serialize in uncompressed, compressed, and hybrid formats. +type PublicKey ecdsa.PublicKey + +// ToECDSA returns the public key as a *ecdsa.PublicKey. +func (p *PublicKey) ToECDSA() *ecdsa.PublicKey { + return (*ecdsa.PublicKey)(p) +} + +// SerializeUncompressed serializes a public key in a 65-byte uncompressed +// format. +func (p *PublicKey) SerializeUncompressed() []byte { + b := make([]byte, 0, PubKeyBytesLenUncompressed) + b = append(b, pubkeyUncompressed) + b = paddedAppend(32, b, p.X.Bytes()) + return paddedAppend(32, b, p.Y.Bytes()) +} + +// SerializeCompressed serializes a public key in a 33-byte compressed format. +func (p *PublicKey) SerializeCompressed() []byte { + b := make([]byte, 0, PubKeyBytesLenCompressed) + format := pubkeyCompressed + if isOdd(p.Y) { + format |= 0x1 + } + b = append(b, format) + return paddedAppend(32, b, p.X.Bytes()) +} + +// SerializeHybrid serializes a public key in a 65-byte hybrid format. +func (p *PublicKey) SerializeHybrid() []byte { + b := make([]byte, 0, PubKeyBytesLenHybrid) + format := pubkeyHybrid + if isOdd(p.Y) { + format |= 0x1 + } + b = append(b, format) + b = paddedAppend(32, b, p.X.Bytes()) + return paddedAppend(32, b, p.Y.Bytes()) +} + +// IsEqual compares this PublicKey instance to the one passed, returning true if +// both PublicKeys are equivalent. A PublicKey is equivalent to another, if they +// both have the same X and Y coordinate. +func (p *PublicKey) IsEqual(otherPubKey *PublicKey) bool { + return p.X.Cmp(otherPubKey.X) == 0 && + p.Y.Cmp(otherPubKey.Y) == 0 +} + +// paddedAppend appends the src byte slice to dst, returning the new slice. +// If the length of the source is smaller than the passed size, leading zero +// bytes are appended to the dst slice before appending src. +func paddedAppend(size uint, dst, src []byte) []byte { + for i := 0; i < int(size)-len(src); i++ { + dst = append(dst, 0) + } + return append(dst, src...) +} diff --git a/vendor/github.com/btcsuite/btcd/btcec/secp256k1.go b/vendor/github.com/btcsuite/btcd/btcec/secp256k1.go new file mode 100644 index 00000000..5e7bffe4 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/secp256k1.go @@ -0,0 +1,10 @@ +// Copyright (c) 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +// Auto-generated file (see genprecomps.go) +// DO NOT EDIT + +var secp256k1BytePoints = "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" diff --git a/vendor/github.com/btcsuite/btcd/btcec/signature.go b/vendor/github.com/btcsuite/btcd/btcec/signature.go new file mode 100644 index 00000000..21826f22 --- /dev/null +++ b/vendor/github.com/btcsuite/btcd/btcec/signature.go @@ -0,0 +1,539 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/hmac" + "crypto/sha256" + "errors" + "fmt" + "hash" + "math/big" +) + +// Errors returned by canonicalPadding. +var ( + errNegativeValue = errors.New("value may be interpreted as negative") + errExcessivelyPaddedValue = errors.New("value is excessively padded") +) + +// Signature is a type representing an ecdsa signature. +type Signature struct { + R *big.Int + S *big.Int +} + +var ( + // Curve order and halforder, used to tame ECDSA malleability (see BIP-0062) + order = new(big.Int).Set(S256().N) + halforder = new(big.Int).Rsh(order, 1) + + // Used in RFC6979 implementation when testing the nonce for correctness + one = big.NewInt(1) + + // oneInitializer is used to fill a byte slice with byte 0x01. It is provided + // here to avoid the need to create it multiple times. + oneInitializer = []byte{0x01} +) + +// Serialize returns the ECDSA signature in the more strict DER format. Note +// that the serialized bytes returned do not include the appended hash type +// used in Bitcoin signature scripts. +// +// encoding/asn1 is broken so we hand roll this output: +// +// 0x30 0x02 r 0x02 s +func (sig *Signature) Serialize() []byte { + // low 'S' malleability breaker + sigS := sig.S + if sigS.Cmp(halforder) == 1 { + sigS = new(big.Int).Sub(order, sigS) + } + // Ensure the encoded bytes for the r and s values are canonical and + // thus suitable for DER encoding. + rb := canonicalizeInt(sig.R) + sb := canonicalizeInt(sigS) + + // 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) + + 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 +} + +// Verify calls ecdsa.Verify to verify the signature of hash using the public +// key. It returns true if the signature is valid, false otherwise. +func (sig *Signature) Verify(hash []byte, pubKey *PublicKey) bool { + return ecdsa.Verify(pubKey.ToECDSA(), hash, sig.R, sig.S) +} + +// IsEqual compares this Signature instance to the one passed, returning true +// if both Signatures are equivalent. A signature is equivalent to another, if +// they both have the same scalar value for R and S. +func (sig *Signature) IsEqual(otherSig *Signature) bool { + return sig.R.Cmp(otherSig.R) == 0 && + sig.S.Cmp(otherSig.S) == 0 +} + +func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) { + // Originally this code used encoding/asn1 in order to parse the + // signature, but a number of problems were found with this approach. + // Despite the fact that signatures are stored as DER, the difference + // between go's idea of a bignum (and that they have sign) doesn't agree + // with the openssl one (where they do not). The above is true as of + // Go 1.1. In the end it was simpler to rewrite the code to explicitly + // understand the format which is this: + // 0x30 <0x02> 0x2 + // . + + signature := &Signature{} + + // minimal message is when both numbers are 1 bytes. adding up to: + // 0x30 + len + 0x02 + 0x01 + + 0x2 + 0x01 + + if len(sigStr) < 8 { + return nil, errors.New("malformed signature: too short") + } + // 0x30 + index := 0 + if sigStr[index] != 0x30 { + return nil, errors.New("malformed signature: no header magic") + } + index++ + // length of remaining message + siglen := sigStr[index] + index++ + if int(siglen+2) > len(sigStr) { + return nil, errors.New("malformed signature: bad length") + } + // trim the slice we're working on so we only look at what matters. + sigStr = sigStr[:siglen+2] + + // 0x02 + if sigStr[index] != 0x02 { + return nil, + errors.New("malformed signature: no 1st int marker") + } + index++ + + // Length of signature R. + rLen := int(sigStr[index]) + // must be positive, must be able to fit in another 0x2, + // hence the -3. We assume that the length must be at least one byte. + index++ + if rLen <= 0 || rLen > len(sigStr)-index-3 { + return nil, errors.New("malformed signature: bogus R length") + } + + // Then R itself. + rBytes := sigStr[index : index+rLen] + if der { + switch err := canonicalPadding(rBytes); err { + case errNegativeValue: + return nil, errors.New("signature R is negative") + case errExcessivelyPaddedValue: + return nil, errors.New("signature R is excessively padded") + } + } + signature.R = new(big.Int).SetBytes(rBytes) + index += rLen + // 0x02. length already checked in previous if. + if sigStr[index] != 0x02 { + return nil, errors.New("malformed signature: no 2nd int marker") + } + index++ + + // Length of signature S. + sLen := int(sigStr[index]) + index++ + // S should be the rest of the string. + if sLen <= 0 || sLen > len(sigStr)-index { + return nil, errors.New("malformed signature: bogus S length") + } + + // Then S itself. + sBytes := sigStr[index : index+sLen] + if der { + switch err := canonicalPadding(sBytes); err { + case errNegativeValue: + return nil, errors.New("signature S is negative") + case errExcessivelyPaddedValue: + return nil, errors.New("signature S is excessively padded") + } + } + signature.S = new(big.Int).SetBytes(sBytes) + index += sLen + + // sanity check length parsing + if index != len(sigStr) { + return nil, fmt.Errorf("malformed signature: bad final length %v != %v", + index, len(sigStr)) + } + + // Verify also checks this, but we can be more sure that we parsed + // correctly if we verify here too. + // FWIW the ecdsa spec states that R and S must be | 1, N - 1 | + // but crypto/ecdsa only checks for Sign != 0. Mirror that. + if signature.R.Sign() != 1 { + return nil, errors.New("signature R isn't 1 or more") + } + if signature.S.Sign() != 1 { + return nil, errors.New("signature S isn't 1 or more") + } + if signature.R.Cmp(curve.Params().N) >= 0 { + return nil, errors.New("signature R is >= curve.N") + } + if signature.S.Cmp(curve.Params().N) >= 0 { + return nil, errors.New("signature S is >= curve.N") + } + + return signature, nil +} + +// ParseSignature parses a signature in BER format for the curve type `curve' +// into a Signature type, perfoming some basic sanity checks. If parsing +// according to the more strict DER format is needed, use ParseDERSignature. +func ParseSignature(sigStr []byte, curve elliptic.Curve) (*Signature, error) { + return parseSig(sigStr, curve, false) +} + +// ParseDERSignature parses a signature in DER format for the curve type +// `curve` into a Signature type. If parsing according to the less strict +// BER format is needed, use ParseSignature. +func ParseDERSignature(sigStr []byte, curve elliptic.Curve) (*Signature, error) { + return parseSig(sigStr, curve, true) +} + +// canonicalizeInt returns the bytes for the passed big integer adjusted as +// necessary to ensure that a big-endian encoded integer can't possibly be +// misinterpreted as a negative number. This can happen when the most +// significant bit is set, so it is padded by a leading zero byte in this case. +// Also, the returned bytes will have at least a single byte when the passed +// value is 0. This is required for DER encoding. +func canonicalizeInt(val *big.Int) []byte { + b := val.Bytes() + if len(b) == 0 { + b = []byte{0x00} + } + if b[0]&0x80 != 0 { + paddedBytes := make([]byte, len(b)+1) + copy(paddedBytes[1:], b) + b = paddedBytes + } + return b +} + +// canonicalPadding checks whether a big-endian encoded integer could +// possibly be misinterpreted as a negative number (even though OpenSSL +// treats all numbers as unsigned), or if there is any unnecessary +// leading zero padding. +func canonicalPadding(b []byte) error { + switch { + case b[0]&0x80 == 0x80: + return errNegativeValue + case len(b) > 1 && b[0] == 0x00 && b[1]&0x80 != 0x80: + return errExcessivelyPaddedValue + default: + return nil + } +} + +// hashToInt converts a hash value to an integer. There is some disagreement +// about how this is done. [NSA] suggests that this is done in the obvious +// manner, but [SECG] truncates the hash to the bit-length of the curve order +// first. We follow [SECG] because that's what OpenSSL does. Additionally, +// OpenSSL right shifts excess bits from the number if the hash is too large +// and we mirror that too. +// This is borrowed from crypto/ecdsa. +func hashToInt(hash []byte, c elliptic.Curve) *big.Int { + orderBits := c.Params().N.BitLen() + orderBytes := (orderBits + 7) / 8 + if len(hash) > orderBytes { + hash = hash[:orderBytes] + } + + ret := new(big.Int).SetBytes(hash) + excess := len(hash)*8 - orderBits + if excess > 0 { + ret.Rsh(ret, uint(excess)) + } + return ret +} + +// recoverKeyFromSignature recoves a public key from the signature "sig" on the +// given message hash "msg". Based on the algorithm found in section 5.1.5 of +// SEC 1 Ver 2.0, page 47-48 (53 and 54 in the pdf). This performs the details +// in the inner loop in Step 1. The counter provided is actually the j parameter +// of the loop * 2 - on the first iteration of j we do the R case, else the -R +// case in step 1.6. This counter is used in the bitcoin compressed signature +// format and thus we match bitcoind's behaviour here. +func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte, + iter int, doChecks bool) (*PublicKey, error) { + // 1.1 x = (n * i) + r + Rx := new(big.Int).Mul(curve.Params().N, + new(big.Int).SetInt64(int64(iter/2))) + Rx.Add(Rx, sig.R) + if Rx.Cmp(curve.Params().P) != -1 { + return nil, errors.New("calculated Rx is larger than curve P") + } + + // convert 02 to point R. (step 1.2 and 1.3). If we are on an odd + // iteration then 1.6 will be done with -R, so we calculate the other + // term when uncompressing the point. + Ry, err := decompressPoint(curve, Rx, iter%2 == 1) + if err != nil { + return nil, err + } + + // 1.4 Check n*R is point at infinity + if doChecks { + nRx, nRy := curve.ScalarMult(Rx, Ry, curve.Params().N.Bytes()) + if nRx.Sign() != 0 || nRy.Sign() != 0 { + return nil, errors.New("n*R does not equal the point at infinity") + } + } + + // 1.5 calculate e from message using the same algorithm as ecdsa + // signature calculation. + e := hashToInt(msg, curve) + + // Step 1.6.1: + // We calculate the two terms sR and eG separately multiplied by the + // inverse of r (from the signature). We then add them to calculate + // Q = r^-1(sR-eG) + invr := new(big.Int).ModInverse(sig.R, curve.Params().N) + + // first term. + invrS := new(big.Int).Mul(invr, sig.S) + invrS.Mod(invrS, curve.Params().N) + sRx, sRy := curve.ScalarMult(Rx, Ry, invrS.Bytes()) + + // second term. + e.Neg(e) + e.Mod(e, curve.Params().N) + e.Mul(e, invr) + e.Mod(e, curve.Params().N) + minuseGx, minuseGy := curve.ScalarBaseMult(e.Bytes()) + + // TODO: this would be faster if we did a mult and add in one + // step to prevent the jacobian conversion back and forth. + Qx, Qy := curve.Add(sRx, sRy, minuseGx, minuseGy) + + return &PublicKey{ + Curve: curve, + X: Qx, + Y: Qy, + }, nil +} + +// SignCompact produces a compact signature of the data in hash with the given +// private key on the given koblitz curve. The isCompressed parameter should +// be used to detail if the given signature should reference a compressed +// public key or not. If successful the bytes of the compact signature will be +// returned in the format: +// <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R> +// where the R and S parameters are padde up to the bitlengh of the curve. +func SignCompact(curve *KoblitzCurve, key *PrivateKey, + hash []byte, isCompressedKey bool) ([]byte, error) { + sig, err := key.Sign(hash) + if err != nil { + return nil, err + } + + // bitcoind checks the bit length of R and S here. The ecdsa signature + // algorithm returns R and S mod N therefore they will be the bitsize of + // the curve, and thus correctly sized. + for i := 0; i < (curve.H+1)*2; i++ { + pk, err := recoverKeyFromSignature(curve, sig, hash, i, true) + if err == nil && pk.X.Cmp(key.X) == 0 && pk.Y.Cmp(key.Y) == 0 { + result := make([]byte, 1, 2*curve.byteSize+1) + result[0] = 27 + byte(i) + if isCompressedKey { + result[0] += 4 + } + // Not sure this needs rounding but safer to do so. + curvelen := (curve.BitSize + 7) / 8 + + // Pad R and S to curvelen if needed. + bytelen := (sig.R.BitLen() + 7) / 8 + if bytelen < curvelen { + result = append(result, + make([]byte, curvelen-bytelen)...) + } + result = append(result, sig.R.Bytes()...) + + bytelen = (sig.S.BitLen() + 7) / 8 + if bytelen < curvelen { + result = append(result, + make([]byte, curvelen-bytelen)...) + } + result = append(result, sig.S.Bytes()...) + + return result, nil + } + } + + return nil, errors.New("no valid solution for pubkey found") +} + +// RecoverCompact verifies the compact signature "signature" of "hash" for the +// Koblitz curve in "curve". If the signature matches then the recovered public +// key will be returned as well as a boolen if the original key was compressed +// or not, else an error will be returned. +func RecoverCompact(curve *KoblitzCurve, signature, + hash []byte) (*PublicKey, bool, error) { + bitlen := (curve.BitSize + 7) / 8 + if len(signature) != 1+bitlen*2 { + return nil, false, errors.New("invalid compact signature size") + } + + iteration := int((signature[0] - 27) & ^byte(4)) + + // format is
+ sig := &Signature{ + R: new(big.Int).SetBytes(signature[1 : bitlen+1]), + S: new(big.Int).SetBytes(signature[bitlen+1:]), + } + // The iteration used here was encoded + key, err := recoverKeyFromSignature(curve, sig, hash, iteration, false) + if err != nil { + return nil, false, err + } + + return key, ((signature[0] - 27) & 4) == 4, nil +} + +// signRFC6979 generates a deterministic ECDSA signature according to RFC 6979 and BIP 62. +func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { + + privkey := privateKey.ToECDSA() + N := order + k := nonceRFC6979(privkey.D, hash) + inv := new(big.Int).ModInverse(k, N) + r, _ := privkey.Curve.ScalarBaseMult(k.Bytes()) + if r.Cmp(N) == 1 { + r.Sub(r, N) + } + + if r.Sign() == 0 { + return nil, errors.New("calculated R is zero") + } + + e := hashToInt(hash, privkey.Curve) + s := new(big.Int).Mul(privkey.D, r) + s.Add(s, e) + s.Mul(s, inv) + s.Mod(s, N) + + if s.Cmp(halforder) == 1 { + s.Sub(N, s) + } + if s.Sign() == 0 { + return nil, errors.New("calculated S is zero") + } + return &Signature{R: r, S: s}, nil +} + +// nonceRFC6979 generates an ECDSA nonce (`k`) deterministically according to RFC 6979. +// It takes a 32-byte hash as an input and returns 32-byte nonce to be used in ECDSA algorithm. +func nonceRFC6979(privkey *big.Int, hash []byte) *big.Int { + + curve := S256() + q := curve.Params().N + x := privkey + alg := sha256.New + + qlen := q.BitLen() + holen := alg().Size() + rolen := (qlen + 7) >> 3 + bx := append(int2octets(x, rolen), bits2octets(hash, curve, rolen)...) + + // Step B + v := bytes.Repeat(oneInitializer, holen) + + // Step C (Go zeroes the all allocated memory) + k := make([]byte, holen) + + // Step D + k = mac(alg, k, append(append(v, 0x00), bx...)) + + // Step E + v = mac(alg, k, v) + + // Step F + k = mac(alg, k, append(append(v, 0x01), bx...)) + + // Step G + v = mac(alg, k, v) + + // Step H + for { + // Step H1 + var t []byte + + // Step H2 + for len(t)*8 < qlen { + v = mac(alg, k, v) + t = append(t, v...) + } + + // Step H3 + secret := hashToInt(t, curve) + if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 { + return secret + } + k = mac(alg, k, append(v, 0x00)) + v = mac(alg, k, v) + } +} + +// mac returns an HMAC of the given key and message. +func mac(alg func() hash.Hash, k, m []byte) []byte { + h := hmac.New(alg, k) + h.Write(m) + return h.Sum(nil) +} + +// https://tools.ietf.org/html/rfc6979#section-2.3.3 +func int2octets(v *big.Int, rolen int) []byte { + out := v.Bytes() + + // left pad with zeros if it's too short + if len(out) < rolen { + out2 := make([]byte, rolen) + copy(out2[rolen-len(out):], out) + return out2 + } + + // drop most significant bytes if it's too long + if len(out) > rolen { + out2 := make([]byte, rolen) + copy(out2, out[len(out)-rolen:]) + return out2 + } + + return out +} + +// https://tools.ietf.org/html/rfc6979#section-2.3.4 +func bits2octets(in []byte, curve elliptic.Curve, rolen int) []byte { + z1 := hashToInt(in, curve) + z2 := new(big.Int).Sub(z1, curve.Params().N) + if z2.Sign() < 0 { + return int2octets(z1, rolen) + } + return int2octets(z2, rolen) +} diff --git a/vendor/github.com/ethereum/go-ethereum/COPYING b/vendor/github.com/ethereum/go-ethereum/COPYING new file mode 100644 index 00000000..8d66e877 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/COPYING @@ -0,0 +1,619 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2014 The go-ethereum Authors. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. \ No newline at end of file diff --git a/vendor/github.com/ethereum/go-ethereum/COPYING.LESSER b/vendor/github.com/ethereum/go-ethereum/COPYING.LESSER new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/COPYING.LESSER @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/github.com/ethereum/go-ethereum/common/big.go b/vendor/github.com/ethereum/go-ethereum/common/big.go new file mode 100644 index 00000000..b552608b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/big.go @@ -0,0 +1,30 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import "math/big" + +// Common big integers often used +var ( + Big1 = big.NewInt(1) + Big2 = big.NewInt(2) + Big3 = big.NewInt(3) + Big0 = big.NewInt(0) + Big32 = big.NewInt(32) + Big256 = big.NewInt(0xff) + Big257 = big.NewInt(257) +) diff --git a/vendor/github.com/ethereum/go-ethereum/common/bytes.go b/vendor/github.com/ethereum/go-ethereum/common/bytes.go new file mode 100644 index 00000000..c445968f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/bytes.go @@ -0,0 +1,111 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package common contains various helper functions. +package common + +import ( + "encoding/hex" +) + +func ToHex(b []byte) string { + hex := Bytes2Hex(b) + // Prefer output of "0x0" instead of "0x" + if len(hex) == 0 { + hex = "0" + } + return "0x" + hex +} + +func FromHex(s string) []byte { + if len(s) > 1 { + if s[0:2] == "0x" || s[0:2] == "0X" { + s = s[2:] + } + if len(s)%2 == 1 { + s = "0" + s + } + return Hex2Bytes(s) + } + return nil +} + +// Copy bytes +// +// Returns an exact copy of the provided bytes +func CopyBytes(b []byte) (copiedBytes []byte) { + copiedBytes = make([]byte, len(b)) + copy(copiedBytes, b) + + return +} + +func HasHexPrefix(str string) bool { + l := len(str) + return l >= 2 && str[0:2] == "0x" +} + +func IsHex(str string) bool { + l := len(str) + return l >= 4 && l%2 == 0 && str[0:2] == "0x" +} + +func Bytes2Hex(d []byte) string { + return hex.EncodeToString(d) +} + +func Hex2Bytes(str string) []byte { + h, _ := hex.DecodeString(str) + + return h +} + +func Hex2BytesFixed(str string, flen int) []byte { + h, _ := hex.DecodeString(str) + if len(h) == flen { + return h + } else { + if len(h) > flen { + return h[len(h)-flen:] + } else { + hh := make([]byte, flen) + copy(hh[flen-len(h):flen], h[:]) + return hh + } + } +} + +func RightPadBytes(slice []byte, l int) []byte { + if l <= len(slice) { + return slice + } + + padded := make([]byte, l) + copy(padded, slice) + + return padded +} + +func LeftPadBytes(slice []byte, l int) []byte { + if l <= len(slice) { + return slice + } + + padded := make([]byte, l) + copy(padded[l-len(slice):], slice) + + return padded +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/debug.go b/vendor/github.com/ethereum/go-ethereum/common/debug.go new file mode 100644 index 00000000..61acd8ce --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/debug.go @@ -0,0 +1,52 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "fmt" + "os" + "runtime" + "runtime/debug" + "strings" +) + +// Report gives off a warning requesting the user to submit an issue to the github tracker. +func Report(extra ...interface{}) { + fmt.Fprintln(os.Stderr, "You've encountered a sought after, hard to reproduce bug. Please report this to the developers <3 https://github.com/ethereum/go-ethereum/issues") + fmt.Fprintln(os.Stderr, extra...) + + _, file, line, _ := runtime.Caller(1) + fmt.Fprintf(os.Stderr, "%v:%v\n", file, line) + + debug.PrintStack() + + fmt.Fprintln(os.Stderr, "#### BUG! PLEASE REPORT ####") +} + +// PrintDepricationWarning prinst the given string in a box using fmt.Println. +func PrintDepricationWarning(str string) { + line := strings.Repeat("#", len(str)+4) + emptyLine := strings.Repeat(" ", len(str)) + fmt.Printf(` +%s +# %s # +# %s # +# %s # +%s + +`, line, emptyLine, str, emptyLine, line) +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/format.go b/vendor/github.com/ethereum/go-ethereum/common/format.go new file mode 100644 index 00000000..fccc2996 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/format.go @@ -0,0 +1,40 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "fmt" + "regexp" + "strings" + "time" +) + +// PrettyDuration is a pretty printed version of a time.Duration value that cuts +// the unnecessary precision off from the formatted textual representation. +type PrettyDuration time.Duration + +var prettyDurationRe = regexp.MustCompile(`\.[0-9]+`) + +// String implements the Stringer interface, allowing pretty printing of duration +// values rounded to three decimals. +func (d PrettyDuration) String() string { + label := fmt.Sprintf("%v", time.Duration(d)) + if match := prettyDurationRe.FindString(label); len(match) > 4 { + label = strings.Replace(label, match, match[:4], 1) + } + return label +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/hexutil/hexutil.go b/vendor/github.com/ethereum/go-ethereum/common/hexutil/hexutil.go new file mode 100644 index 00000000..6b128ae3 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/hexutil/hexutil.go @@ -0,0 +1,236 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +/* +Package hexutil implements hex encoding with 0x prefix. +This encoding is used by the Ethereum RPC API to transport binary data in JSON payloads. + +Encoding Rules + +All hex data must have prefix "0x". + +For byte slices, the hex data must be of even length. An empty byte slice +encodes as "0x". + +Integers are encoded using the least amount of digits (no leading zero digits). Their +encoding may be of uneven length. The number zero encodes as "0x0". +*/ +package hexutil + +import ( + "encoding/hex" + "errors" + "fmt" + "math/big" + "strconv" +) + +const uintBits = 32 << (uint64(^uint(0)) >> 63) + +var ( + ErrEmptyString = errors.New("empty hex string") + ErrMissingPrefix = errors.New("missing 0x prefix for hex data") + ErrSyntax = errors.New("invalid hex") + ErrEmptyNumber = errors.New("hex number has no digits after 0x") + ErrLeadingZero = errors.New("hex number has leading zero digits after 0x") + ErrOddLength = errors.New("hex string has odd length") + ErrUint64Range = errors.New("hex number does not fit into 64 bits") + ErrUintRange = fmt.Errorf("hex number does not fit into %d bits", uintBits) + ErrBig256Range = errors.New("hex number does not fit into 256 bits") +) + +// Decode decodes a hex string with 0x prefix. +func Decode(input string) ([]byte, error) { + if len(input) == 0 { + return nil, ErrEmptyString + } + if !has0xPrefix(input) { + return nil, ErrMissingPrefix + } + b, err := hex.DecodeString(input[2:]) + if err != nil { + err = mapError(err) + } + return b, err +} + +// MustDecode decodes a hex string with 0x prefix. It panics for invalid input. +func MustDecode(input string) []byte { + dec, err := Decode(input) + if err != nil { + panic(err) + } + return dec +} + +// Encode encodes b as a hex string with 0x prefix. +func Encode(b []byte) string { + enc := make([]byte, len(b)*2+2) + copy(enc, "0x") + hex.Encode(enc[2:], b) + return string(enc) +} + +// DecodeUint64 decodes a hex string with 0x prefix as a quantity. +func DecodeUint64(input string) (uint64, error) { + raw, err := checkNumber(input) + if err != nil { + return 0, err + } + dec, err := strconv.ParseUint(raw, 16, 64) + if err != nil { + err = mapError(err) + } + return dec, err +} + +// MustDecodeUint64 decodes a hex string with 0x prefix as a quantity. +// It panics for invalid input. +func MustDecodeUint64(input string) uint64 { + dec, err := DecodeUint64(input) + if err != nil { + panic(err) + } + return dec +} + +// EncodeUint64 encodes i as a hex string with 0x prefix. +func EncodeUint64(i uint64) string { + enc := make([]byte, 2, 10) + copy(enc, "0x") + return string(strconv.AppendUint(enc, i, 16)) +} + +var bigWordNibbles int + +func init() { + // This is a weird way to compute the number of nibbles required for big.Word. + // The usual way would be to use constant arithmetic but go vet can't handle that. + b, _ := new(big.Int).SetString("FFFFFFFFFF", 16) + switch len(b.Bits()) { + case 1: + bigWordNibbles = 16 + case 2: + bigWordNibbles = 8 + default: + panic("weird big.Word size") + } +} + +// DecodeBig decodes a hex string with 0x prefix as a quantity. +// Numbers larger than 256 bits are not accepted. +func DecodeBig(input string) (*big.Int, error) { + raw, err := checkNumber(input) + if err != nil { + return nil, err + } + if len(raw) > 64 { + return nil, ErrBig256Range + } + words := make([]big.Word, len(raw)/bigWordNibbles+1) + end := len(raw) + for i := range words { + start := end - bigWordNibbles + if start < 0 { + start = 0 + } + for ri := start; ri < end; ri++ { + nib := decodeNibble(raw[ri]) + if nib == badNibble { + return nil, ErrSyntax + } + words[i] *= 16 + words[i] += big.Word(nib) + } + end = start + } + dec := new(big.Int).SetBits(words) + return dec, nil +} + +// MustDecodeBig decodes a hex string with 0x prefix as a quantity. +// It panics for invalid input. +func MustDecodeBig(input string) *big.Int { + dec, err := DecodeBig(input) + if err != nil { + panic(err) + } + return dec +} + +// EncodeBig encodes bigint as a hex string with 0x prefix. +// The sign of the integer is ignored. +func EncodeBig(bigint *big.Int) string { + nbits := bigint.BitLen() + if nbits == 0 { + return "0x0" + } + return fmt.Sprintf("%#x", bigint) +} + +func has0xPrefix(input string) bool { + return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') +} + +func checkNumber(input string) (raw string, err error) { + if len(input) == 0 { + return "", ErrEmptyString + } + if !has0xPrefix(input) { + return "", ErrMissingPrefix + } + input = input[2:] + if len(input) == 0 { + return "", ErrEmptyNumber + } + if len(input) > 1 && input[0] == '0' { + return "", ErrLeadingZero + } + return input, nil +} + +const badNibble = ^uint64(0) + +func decodeNibble(in byte) uint64 { + switch { + case in >= '0' && in <= '9': + return uint64(in - '0') + case in >= 'A' && in <= 'F': + return uint64(in - 'A' + 10) + case in >= 'a' && in <= 'f': + return uint64(in - 'a' + 10) + default: + return badNibble + } +} + +func mapError(err error) error { + if err, ok := err.(*strconv.NumError); ok { + switch err.Err { + case strconv.ErrRange: + return ErrUint64Range + case strconv.ErrSyntax: + return ErrSyntax + } + } + if _, ok := err.(hex.InvalidByteError); ok { + return ErrSyntax + } + if err == hex.ErrLength { + return ErrOddLength + } + return err +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go b/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go new file mode 100644 index 00000000..1bc1d014 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go @@ -0,0 +1,297 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package hexutil + +import ( + "encoding/hex" + "errors" + "fmt" + "math/big" + "strconv" +) + +var ( + textZero = []byte(`0x0`) + errNonString = errors.New("cannot unmarshal non-string as hex data") +) + +// Bytes marshals/unmarshals as a JSON string with 0x prefix. +// The empty slice marshals as "0x". +type Bytes []byte + +// MarshalText implements encoding.TextMarshaler +func (b Bytes) MarshalText() ([]byte, error) { + result := make([]byte, len(b)*2+2) + copy(result, `0x`) + hex.Encode(result[2:], b) + return result, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (b *Bytes) UnmarshalJSON(input []byte) error { + if !isString(input) { + return errNonString + } + return b.UnmarshalText(input[1 : len(input)-1]) +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (b *Bytes) UnmarshalText(input []byte) error { + raw, err := checkText(input, true) + if err != nil { + return err + } + dec := make([]byte, len(raw)/2) + if _, err = hex.Decode(dec, raw); err != nil { + err = mapError(err) + } else { + *b = dec + } + return err +} + +// String returns the hex encoding of b. +func (b Bytes) String() string { + return Encode(b) +} + +// UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out +// determines the required input length. This function is commonly used to implement the +// UnmarshalText method for fixed-size types. +func UnmarshalFixedText(typname string, input, out []byte) error { + raw, err := checkText(input, true) + if err != nil { + return err + } + if len(raw)/2 != len(out) { + return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) + } + // Pre-verify syntax before modifying out. + for _, b := range raw { + if decodeNibble(b) == badNibble { + return ErrSyntax + } + } + hex.Decode(out, raw) + return nil +} + +// UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The +// length of out determines the required input length. This function is commonly used to +// implement the UnmarshalText method for fixed-size types. +func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error { + raw, err := checkText(input, false) + if err != nil { + return err + } + if len(raw)/2 != len(out) { + return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) + } + // Pre-verify syntax before modifying out. + for _, b := range raw { + if decodeNibble(b) == badNibble { + return ErrSyntax + } + } + hex.Decode(out, raw) + return nil +} + +// Big marshals/unmarshals as a JSON string with 0x prefix. +// The zero value marshals as "0x0". +// +// Negative integers are not supported at this time. Attempting to marshal them will +// return an error. Values larger than 256bits are rejected by Unmarshal but will be +// marshaled without error. +type Big big.Int + +// MarshalText implements encoding.TextMarshaler +func (b Big) MarshalText() ([]byte, error) { + return []byte(EncodeBig((*big.Int)(&b))), nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (b *Big) UnmarshalJSON(input []byte) error { + if !isString(input) { + return errNonString + } + return b.UnmarshalText(input[1 : len(input)-1]) +} + +// UnmarshalText implements encoding.TextUnmarshaler +func (b *Big) UnmarshalText(input []byte) error { + raw, err := checkNumberText(input) + if err != nil { + return err + } + if len(raw) > 64 { + return ErrBig256Range + } + words := make([]big.Word, len(raw)/bigWordNibbles+1) + end := len(raw) + for i := range words { + start := end - bigWordNibbles + if start < 0 { + start = 0 + } + for ri := start; ri < end; ri++ { + nib := decodeNibble(raw[ri]) + if nib == badNibble { + return ErrSyntax + } + words[i] *= 16 + words[i] += big.Word(nib) + } + end = start + } + var dec big.Int + dec.SetBits(words) + *b = (Big)(dec) + return nil +} + +// ToInt converts b to a big.Int. +func (b *Big) ToInt() *big.Int { + return (*big.Int)(b) +} + +// String returns the hex encoding of b. +func (b *Big) String() string { + return EncodeBig(b.ToInt()) +} + +// Uint64 marshals/unmarshals as a JSON string with 0x prefix. +// The zero value marshals as "0x0". +type Uint64 uint64 + +// MarshalText implements encoding.TextMarshaler. +func (b Uint64) MarshalText() ([]byte, error) { + buf := make([]byte, 2, 10) + copy(buf, `0x`) + buf = strconv.AppendUint(buf, uint64(b), 16) + return buf, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (b *Uint64) UnmarshalJSON(input []byte) error { + if !isString(input) { + return errNonString + } + return b.UnmarshalText(input[1 : len(input)-1]) +} + +// UnmarshalText implements encoding.TextUnmarshaler +func (b *Uint64) UnmarshalText(input []byte) error { + raw, err := checkNumberText(input) + if err != nil { + return err + } + if len(raw) > 16 { + return ErrUint64Range + } + var dec uint64 + for _, byte := range raw { + nib := decodeNibble(byte) + if nib == badNibble { + return ErrSyntax + } + dec *= 16 + dec += uint64(nib) + } + *b = Uint64(dec) + return nil +} + +// String returns the hex encoding of b. +func (b Uint64) String() string { + return EncodeUint64(uint64(b)) +} + +// Uint marshals/unmarshals as a JSON string with 0x prefix. +// The zero value marshals as "0x0". +type Uint uint + +// MarshalText implements encoding.TextMarshaler. +func (b Uint) MarshalText() ([]byte, error) { + return Uint64(b).MarshalText() +} + +// UnmarshalJSON implements json.Unmarshaler. +func (b *Uint) UnmarshalJSON(input []byte) error { + if !isString(input) { + return errNonString + } + return b.UnmarshalText(input[1 : len(input)-1]) +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (b *Uint) UnmarshalText(input []byte) error { + var u64 Uint64 + err := u64.UnmarshalText(input) + if u64 > Uint64(^uint(0)) || err == ErrUint64Range { + return ErrUintRange + } else if err != nil { + return err + } + *b = Uint(u64) + return nil +} + +// String returns the hex encoding of b. +func (b Uint) String() string { + return EncodeUint64(uint64(b)) +} + +func isString(input []byte) bool { + return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' +} + +func bytesHave0xPrefix(input []byte) bool { + return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') +} + +func checkText(input []byte, wantPrefix bool) ([]byte, error) { + if len(input) == 0 { + return nil, nil // empty strings are allowed + } + if bytesHave0xPrefix(input) { + input = input[2:] + } else if wantPrefix { + return nil, ErrMissingPrefix + } + if len(input)%2 != 0 { + return nil, ErrOddLength + } + return input, nil +} + +func checkNumberText(input []byte) (raw []byte, err error) { + if len(input) == 0 { + return nil, nil // empty strings are allowed + } + if !bytesHave0xPrefix(input) { + return nil, ErrMissingPrefix + } + input = input[2:] + if len(input) == 0 { + return nil, ErrEmptyNumber + } + if len(input) > 1 && input[0] == '0' { + return nil, ErrLeadingZero + } + return input, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/math/big.go b/vendor/github.com/ethereum/go-ethereum/common/math/big.go new file mode 100644 index 00000000..78727865 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/math/big.go @@ -0,0 +1,212 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package math provides integer math utilities. +package math + +import ( + "fmt" + "math/big" +) + +var ( + tt255 = BigPow(2, 255) + tt256 = BigPow(2, 256) + tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1)) + MaxBig256 = new(big.Int).Set(tt256m1) + tt63 = BigPow(2, 63) + MaxBig63 = new(big.Int).Sub(tt63, big.NewInt(1)) +) + +const ( + // number of bits in a big.Word + wordBits = 32 << (uint64(^big.Word(0)) >> 63) + // number of bytes in a big.Word + wordBytes = wordBits / 8 +) + +// HexOrDecimal256 marshals big.Int as hex or decimal. +type HexOrDecimal256 big.Int + +// UnmarshalText implements encoding.TextUnmarshaler. +func (i *HexOrDecimal256) UnmarshalText(input []byte) error { + bigint, ok := ParseBig256(string(input)) + if !ok { + return fmt.Errorf("invalid hex or decimal integer %q", input) + } + *i = HexOrDecimal256(*bigint) + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (i *HexOrDecimal256) MarshalText() ([]byte, error) { + if i == nil { + return []byte("0x0"), nil + } + return []byte(fmt.Sprintf("%#x", (*big.Int)(i))), nil +} + +// ParseBig256 parses s as a 256 bit integer in decimal or hexadecimal syntax. +// Leading zeros are accepted. The empty string parses as zero. +func ParseBig256(s string) (*big.Int, bool) { + if s == "" { + return new(big.Int), true + } + var bigint *big.Int + var ok bool + if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { + bigint, ok = new(big.Int).SetString(s[2:], 16) + } else { + bigint, ok = new(big.Int).SetString(s, 10) + } + if ok && bigint.BitLen() > 256 { + bigint, ok = nil, false + } + return bigint, ok +} + +// MustParseBig parses s as a 256 bit big integer and panics if the string is invalid. +func MustParseBig256(s string) *big.Int { + v, ok := ParseBig256(s) + if !ok { + panic("invalid 256 bit integer: " + s) + } + return v +} + +// BigPow returns a ** b as a big integer. +func BigPow(a, b int64) *big.Int { + r := big.NewInt(a) + return r.Exp(r, big.NewInt(b), nil) +} + +// BigMax returns the larger of x or y. +func BigMax(x, y *big.Int) *big.Int { + if x.Cmp(y) < 0 { + return y + } + return x +} + +// BigMin returns the smaller of x or y. +func BigMin(x, y *big.Int) *big.Int { + if x.Cmp(y) > 0 { + return y + } + return x +} + +// FirstBitSet returns the index of the first 1 bit in v, counting from LSB. +func FirstBitSet(v *big.Int) int { + for i := 0; i < v.BitLen(); i++ { + if v.Bit(i) > 0 { + return i + } + } + return v.BitLen() +} + +// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length +// of the slice is at least n bytes. +func PaddedBigBytes(bigint *big.Int, n int) []byte { + if bigint.BitLen()/8 >= n { + return bigint.Bytes() + } + ret := make([]byte, n) + ReadBits(bigint, ret) + return ret +} + +// bigEndianByteAt returns the byte at position n, +// in Big-Endian encoding +// So n==0 returns the least significant byte +func bigEndianByteAt(bigint *big.Int, n int) byte { + words := bigint.Bits() + // Check word-bucket the byte will reside in + i := n / wordBytes + if i >= len(words) { + return byte(0) + } + word := words[i] + // Offset of the byte + shift := 8 * uint(n%wordBytes) + + return byte(word >> shift) +} + +// Byte returns the byte at position n, +// with the supplied padlength in Little-Endian encoding. +// n==0 returns the MSB +// Example: bigint '5', padlength 32, n=31 => 5 +func Byte(bigint *big.Int, padlength, n int) byte { + if n >= padlength { + return byte(0) + } + return bigEndianByteAt(bigint, padlength-1-n) +} + +// ReadBits encodes the absolute value of bigint as big-endian bytes. Callers must ensure +// that buf has enough space. If buf is too short the result will be incomplete. +func ReadBits(bigint *big.Int, buf []byte) { + i := len(buf) + for _, d := range bigint.Bits() { + for j := 0; j < wordBytes && i > 0; j++ { + i-- + buf[i] = byte(d) + d >>= 8 + } + } +} + +// U256 encodes as a 256 bit two's complement number. This operation is destructive. +func U256(x *big.Int) *big.Int { + return x.And(x, tt256m1) +} + +// S256 interprets x as a two's complement number. +// x must not exceed 256 bits (the result is undefined if it does) and is not modified. +// +// S256(0) = 0 +// S256(1) = 1 +// S256(2**255) = -2**255 +// S256(2**256-1) = -1 +func S256(x *big.Int) *big.Int { + if x.Cmp(tt255) < 0 { + return x + } else { + return new(big.Int).Sub(x, tt256) + } +} + +// Exp implements exponentiation by squaring. +// Exp returns a newly-allocated big integer and does not change +// base or exponent. The result is truncated to 256 bits. +// +// Courtesy @karalabe and @chfast +func Exp(base, exponent *big.Int) *big.Int { + result := big.NewInt(1) + + for _, word := range exponent.Bits() { + for i := 0; i < wordBits; i++ { + if word&1 == 1 { + U256(result.Mul(result, base)) + } + U256(base.Mul(base, base)) + word >>= 1 + } + } + return result +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/math/integer.go b/vendor/github.com/ethereum/go-ethereum/common/math/integer.go new file mode 100644 index 00000000..7eff4d3b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/math/integer.go @@ -0,0 +1,99 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package math + +import ( + "fmt" + "strconv" +) + +const ( + // Integer limit values. + MaxInt8 = 1<<7 - 1 + MinInt8 = -1 << 7 + MaxInt16 = 1<<15 - 1 + MinInt16 = -1 << 15 + MaxInt32 = 1<<31 - 1 + MinInt32 = -1 << 31 + MaxInt64 = 1<<63 - 1 + MinInt64 = -1 << 63 + MaxUint8 = 1<<8 - 1 + MaxUint16 = 1<<16 - 1 + MaxUint32 = 1<<32 - 1 + MaxUint64 = 1<<64 - 1 +) + +// HexOrDecimal64 marshals uint64 as hex or decimal. +type HexOrDecimal64 uint64 + +// UnmarshalText implements encoding.TextUnmarshaler. +func (i *HexOrDecimal64) UnmarshalText(input []byte) error { + int, ok := ParseUint64(string(input)) + if !ok { + return fmt.Errorf("invalid hex or decimal integer %q", input) + } + *i = HexOrDecimal64(int) + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (i HexOrDecimal64) MarshalText() ([]byte, error) { + return []byte(fmt.Sprintf("%#x", uint64(i))), nil +} + +// ParseUint64 parses s as an integer in decimal or hexadecimal syntax. +// Leading zeros are accepted. The empty string parses as zero. +func ParseUint64(s string) (uint64, bool) { + if s == "" { + return 0, true + } + if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { + v, err := strconv.ParseUint(s[2:], 16, 64) + return v, err == nil + } + v, err := strconv.ParseUint(s, 10, 64) + return v, err == nil +} + +// MustParseUint64 parses s as an integer and panics if the string is invalid. +func MustParseUint64(s string) uint64 { + v, ok := ParseUint64(s) + if !ok { + panic("invalid unsigned 64 bit integer: " + s) + } + return v +} + +// NOTE: The following methods need to be optimised using either bit checking or asm + +// SafeSub returns subtraction result and whether overflow occurred. +func SafeSub(x, y uint64) (uint64, bool) { + return x - y, x < y +} + +// SafeAdd returns the result and whether overflow occurred. +func SafeAdd(x, y uint64) (uint64, bool) { + return x + y, y > MaxUint64-x +} + +// SafeMul returns multiplication result and whether overflow occurred. +func SafeMul(x, y uint64) (uint64, bool) { + if x == 0 || y == 0 { + return 0, false + } + return x * y, y > MaxUint64/x +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/path.go b/vendor/github.com/ethereum/go-ethereum/common/path.go new file mode 100644 index 00000000..bd8da86e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/path.go @@ -0,0 +1,47 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "fmt" + "os" + "path/filepath" + "runtime" +) + +// MakeName creates a node name that follows the ethereum convention +// for such names. It adds the operation system name and Go runtime version +// the name. +func MakeName(name, version string) string { + return fmt.Sprintf("%s/v%s/%s/%s", name, version, runtime.GOOS, runtime.Version()) +} + +func FileExist(filePath string) bool { + _, err := os.Stat(filePath) + if err != nil && os.IsNotExist(err) { + return false + } + + return true +} + +func AbsolutePath(Datadir string, filename string) string { + if filepath.IsAbs(filename) { + return filename + } + return filepath.Join(Datadir, filename) +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/size.go b/vendor/github.com/ethereum/go-ethereum/common/size.go new file mode 100644 index 00000000..c5a0cb0f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/size.go @@ -0,0 +1,37 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "fmt" +) + +type StorageSize float64 + +func (self StorageSize) String() string { + if self > 1000000 { + return fmt.Sprintf("%.2f mB", self/1000000) + } else if self > 1000 { + return fmt.Sprintf("%.2f kB", self/1000) + } else { + return fmt.Sprintf("%.2f B", self) + } +} + +func (self StorageSize) Int64() int64 { + return int64(self) +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/test_utils.go b/vendor/github.com/ethereum/go-ethereum/common/test_utils.go new file mode 100644 index 00000000..a848642f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/test_utils.go @@ -0,0 +1,53 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "encoding/json" + "fmt" + "io/ioutil" +) + +// LoadJSON reads the given file and unmarshals its content. +func LoadJSON(file string, val interface{}) error { + content, err := ioutil.ReadFile(file) + if err != nil { + return err + } + if err := json.Unmarshal(content, val); err != nil { + if syntaxerr, ok := err.(*json.SyntaxError); ok { + line := findLine(content, syntaxerr.Offset) + return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err) + } + return fmt.Errorf("JSON unmarshal error in %v: %v", file, err) + } + return nil +} + +// findLine returns the line number for the given offset into data. +func findLine(data []byte, offset int64) (line int) { + line = 1 + for i, r := range string(data) { + if int64(i) >= offset { + return + } + if r == '\n' { + line++ + } + } + return +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/types.go b/vendor/github.com/ethereum/go-ethereum/common/types.go new file mode 100644 index 00000000..05288bf4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/types.go @@ -0,0 +1,208 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "encoding/hex" + "fmt" + "math/big" + "math/rand" + "reflect" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +const ( + HashLength = 32 + AddressLength = 20 +) + +// Hash represents the 32 byte Keccak256 hash of arbitrary data. +type Hash [HashLength]byte + +func BytesToHash(b []byte) Hash { + var h Hash + h.SetBytes(b) + return h +} +func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } +func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } +func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } + +// Get the string representation of the underlying hash +func (h Hash) Str() string { return string(h[:]) } +func (h Hash) Bytes() []byte { return h[:] } +func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } +func (h Hash) Hex() string { return hexutil.Encode(h[:]) } + +// TerminalString implements log.TerminalStringer, formatting a string for console +// output during logging. +func (h Hash) TerminalString() string { + return fmt.Sprintf("%x…%x", h[:3], h[29:]) +} + +// String implements the stringer interface and is used also by the logger when +// doing full logging into a file. +func (h Hash) String() string { + return h.Hex() +} + +// Format implements fmt.Formatter, forcing the byte slice to be formatted as is, +// without going through the stringer interface used for logging. +func (h Hash) Format(s fmt.State, c rune) { + fmt.Fprintf(s, "%"+string(c), h[:]) +} + +// UnmarshalText parses a hash in hex syntax. +func (h *Hash) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedText("Hash", input, h[:]) +} + +// MarshalText returns the hex representation of h. +func (h Hash) MarshalText() ([]byte, error) { + return hexutil.Bytes(h[:]).MarshalText() +} + +// Sets the hash to the value of b. If b is larger than len(h) it will panic +func (h *Hash) SetBytes(b []byte) { + if len(b) > len(h) { + b = b[len(b)-HashLength:] + } + + copy(h[HashLength-len(b):], b) +} + +// Set string `s` to h. If s is larger than len(h) it will panic +func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) } + +// Sets h to other +func (h *Hash) Set(other Hash) { + for i, v := range other { + h[i] = v + } +} + +// Generate implements testing/quick.Generator. +func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { + m := rand.Intn(len(h)) + for i := len(h) - 1; i > m; i-- { + h[i] = byte(rand.Uint32()) + } + return reflect.ValueOf(h) +} + +func EmptyHash(h Hash) bool { + return h == Hash{} +} + +// UnprefixedHash allows marshaling a Hash without 0x prefix. +type UnprefixedHash Hash + +// UnmarshalText decodes the hash from hex. The 0x prefix is optional. +func (h *UnprefixedHash) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:]) +} + +// MarshalText encodes the hash as hex. +func (h UnprefixedHash) MarshalText() ([]byte, error) { + return []byte(hex.EncodeToString(h[:])), nil +} + +/////////// Address + +// Address represents the 20 byte address of an Ethereum account. +type Address [AddressLength]byte + +func BytesToAddress(b []byte) Address { + var a Address + a.SetBytes(b) + return a +} +func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) } +func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } +func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } + +// IsHexAddress verifies whether a string can represent a valid hex-encoded +// Ethereum address or not. +func IsHexAddress(s string) bool { + if len(s) == 2+2*AddressLength && IsHex(s) { + return true + } + if len(s) == 2*AddressLength && IsHex("0x"+s) { + return true + } + return false +} + +// Get the string representation of the underlying address +func (a Address) Str() string { return string(a[:]) } +func (a Address) Bytes() []byte { return a[:] } +func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } +func (a Address) Hash() Hash { return BytesToHash(a[:]) } +func (a Address) Hex() string { return hexutil.Encode(a[:]) } + +// String implements the stringer interface and is used also by the logger. +func (a Address) String() string { + return a.Hex() +} + +// Format implements fmt.Formatter, forcing the byte slice to be formatted as is, +// without going through the stringer interface used for logging. +func (a Address) Format(s fmt.State, c rune) { + fmt.Fprintf(s, "%"+string(c), a[:]) +} + +// Sets the address to the value of b. If b is larger than len(a) it will panic +func (a *Address) SetBytes(b []byte) { + if len(b) > len(a) { + b = b[len(b)-AddressLength:] + } + copy(a[AddressLength-len(b):], b) +} + +// Set string `s` to a. If s is larger than len(a) it will panic +func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) } + +// Sets a to other +func (a *Address) Set(other Address) { + for i, v := range other { + a[i] = v + } +} + +// MarshalText returns the hex representation of a. +func (a Address) MarshalText() ([]byte, error) { + return hexutil.Bytes(a[:]).MarshalText() +} + +// UnmarshalText parses a hash in hex syntax. +func (a *Address) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedText("Address", input, a[:]) +} + +// UnprefixedHash allows marshaling an Address without 0x prefix. +type UnprefixedAddress Address + +// UnmarshalText decodes the address from hex. The 0x prefix is optional. +func (a *UnprefixedAddress) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:]) +} + +// MarshalText encodes the address as hex. +func (a UnprefixedAddress) MarshalText() ([]byte, error) { + return []byte(hex.EncodeToString(a[:])), nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/common/types_template.go b/vendor/github.com/ethereum/go-ethereum/common/types_template.go new file mode 100644 index 00000000..9a8f2997 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/common/types_template.go @@ -0,0 +1,64 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build none +//sed -e 's/_N_/Hash/g' -e 's/_S_/32/g' -e '1d' types_template.go | gofmt -w hash.go + +package common + +import "math/big" + +type _N_ [_S_]byte + +func BytesTo_N_(b []byte) _N_ { + var h _N_ + h.SetBytes(b) + return h +} +func StringTo_N_(s string) _N_ { return BytesTo_N_([]byte(s)) } +func BigTo_N_(b *big.Int) _N_ { return BytesTo_N_(b.Bytes()) } +func HexTo_N_(s string) _N_ { return BytesTo_N_(FromHex(s)) } + +// Don't use the default 'String' method in case we want to overwrite + +// Get the string representation of the underlying hash +func (h _N_) Str() string { return string(h[:]) } +func (h _N_) Bytes() []byte { return h[:] } +func (h _N_) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } +func (h _N_) Hex() string { return "0x" + Bytes2Hex(h[:]) } + +// Sets the hash to the value of b. If b is larger than len(h) it will panic +func (h *_N_) SetBytes(b []byte) { + // Use the right most bytes + if len(b) > len(h) { + b = b[len(b)-_S_:] + } + + // Reverse the loop + for i := len(b) - 1; i >= 0; i-- { + h[_S_-len(b)+i] = b[i] + } +} + +// Set string `s` to h. If s is larger than len(h) it will panic +func (h *_N_) SetString(s string) { h.SetBytes([]byte(s)) } + +// Sets h to other +func (h *_N_) Set(other _N_) { + for i, v := range other { + h[i] = v + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go b/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go new file mode 100644 index 00000000..8161769d --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/crypto.go @@ -0,0 +1,190 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package crypto + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "encoding/hex" + "errors" + "fmt" + "io" + "io/ioutil" + "math/big" + "os" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto/sha3" + "github.com/ethereum/go-ethereum/rlp" +) + +var ( + secp256k1_N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16) + secp256k1_halfN = new(big.Int).Div(secp256k1_N, big.NewInt(2)) +) + +// Keccak256 calculates and returns the Keccak256 hash of the input data. +func Keccak256(data ...[]byte) []byte { + d := sha3.NewKeccak256() + for _, b := range data { + d.Write(b) + } + return d.Sum(nil) +} + +// Keccak256Hash calculates and returns the Keccak256 hash of the input data, +// converting it to an internal Hash data structure. +func Keccak256Hash(data ...[]byte) (h common.Hash) { + d := sha3.NewKeccak256() + for _, b := range data { + d.Write(b) + } + d.Sum(h[:0]) + return h +} + +// Keccak512 calculates and returns the Keccak512 hash of the input data. +func Keccak512(data ...[]byte) []byte { + d := sha3.NewKeccak512() + for _, b := range data { + d.Write(b) + } + return d.Sum(nil) +} + +// Creates an ethereum address given the bytes and the nonce +func CreateAddress(b common.Address, nonce uint64) common.Address { + data, _ := rlp.EncodeToBytes([]interface{}{b, nonce}) + return common.BytesToAddress(Keccak256(data)[12:]) +} + +// ToECDSA creates a private key with the given D value. +func ToECDSA(d []byte) (*ecdsa.PrivateKey, error) { + return toECDSA(d, true) +} + +// ToECDSAUnsafe blidly converts a binary blob to a private key. It should almost +// never be used unless you are sure the input is valid and want to avoid hitting +// errors due to bad origin encoding (0 prefixes cut off). +func ToECDSAUnsafe(d []byte) *ecdsa.PrivateKey { + priv, _ := toECDSA(d, false) + return priv +} + +// toECDSA creates a private key with the given D value. The strict parameter +// controls whether the key's length should be enforced at the curve size or +// it can also accept legacy encodings (0 prefixes). +func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) { + priv := new(ecdsa.PrivateKey) + priv.PublicKey.Curve = S256() + if strict && 8*len(d) != priv.Params().BitSize { + return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize) + } + priv.D = new(big.Int).SetBytes(d) + priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d) + return priv, nil +} + +// FromECDSA exports a private key into a binary dump. +func FromECDSA(priv *ecdsa.PrivateKey) []byte { + if priv == nil { + return nil + } + return math.PaddedBigBytes(priv.D, priv.Params().BitSize/8) +} + +func ToECDSAPub(pub []byte) *ecdsa.PublicKey { + if len(pub) == 0 { + return nil + } + x, y := elliptic.Unmarshal(S256(), pub) + return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y} +} + +func FromECDSAPub(pub *ecdsa.PublicKey) []byte { + if pub == nil || pub.X == nil || pub.Y == nil { + return nil + } + return elliptic.Marshal(S256(), pub.X, pub.Y) +} + +// HexToECDSA parses a secp256k1 private key. +func HexToECDSA(hexkey string) (*ecdsa.PrivateKey, error) { + b, err := hex.DecodeString(hexkey) + if err != nil { + return nil, errors.New("invalid hex string") + } + return ToECDSA(b) +} + +// LoadECDSA loads a secp256k1 private key from the given file. +func LoadECDSA(file string) (*ecdsa.PrivateKey, error) { + buf := make([]byte, 64) + fd, err := os.Open(file) + if err != nil { + return nil, err + } + defer fd.Close() + if _, err := io.ReadFull(fd, buf); err != nil { + return nil, err + } + + key, err := hex.DecodeString(string(buf)) + if err != nil { + return nil, err + } + return ToECDSA(key) +} + +// SaveECDSA saves a secp256k1 private key to the given file with +// restrictive permissions. The key data is saved hex-encoded. +func SaveECDSA(file string, key *ecdsa.PrivateKey) error { + k := hex.EncodeToString(FromECDSA(key)) + return ioutil.WriteFile(file, []byte(k), 0600) +} + +func GenerateKey() (*ecdsa.PrivateKey, error) { + return ecdsa.GenerateKey(S256(), rand.Reader) +} + +// ValidateSignatureValues verifies whether the signature values are valid with +// the given chain rules. The v value is assumed to be either 0 or 1. +func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool { + if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 { + return false + } + // reject upper range of s values (ECDSA malleability) + // see discussion in secp256k1/libsecp256k1/include/secp256k1.h + if homestead && s.Cmp(secp256k1_halfN) > 0 { + return false + } + // Frontier: allow s to be in full N range + return r.Cmp(secp256k1_N) < 0 && s.Cmp(secp256k1_N) < 0 && (v == 0 || v == 1) +} + +func PubkeyToAddress(p ecdsa.PublicKey) common.Address { + pubBytes := FromECDSAPub(&p) + return common.BytesToAddress(Keccak256(pubBytes[1:])[12:]) +} + +func zeroBytes(bytes []byte) { + for i := range bytes { + bytes[i] = 0 + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/curve.go b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/curve.go new file mode 100644 index 00000000..ec6d266c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/curve.go @@ -0,0 +1,312 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Copyright 2011 ThePiachu. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// * The name of ThePiachu may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package secp256k1 + +import ( + "crypto/elliptic" + "math/big" + "sync" + "unsafe" + + "github.com/ethereum/go-ethereum/common/math" +) + +/* +#include "libsecp256k1/include/secp256k1.h" +extern int secp256k1_pubkey_scalar_mul(const secp256k1_context* ctx, const unsigned char *point, const unsigned char *scalar); +*/ +import "C" + +// This code is from https://github.com/ThePiachu/GoBit and implements +// several Koblitz elliptic curves over prime fields. +// +// The curve methods, internally, on Jacobian coordinates. For a given +// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, +// z1) where x = x1/z1² and y = y1/z1³. The greatest speedups come +// when the whole calculation can be performed within the transform +// (as in ScalarMult and ScalarBaseMult). But even for Add and Double, +// it's faster to apply and reverse the transform than to operate in +// affine coordinates. + +// A BitCurve represents a Koblitz Curve with a=0. +// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html +type BitCurve struct { + P *big.Int // the order of the underlying field + N *big.Int // the order of the base point + B *big.Int // the constant of the BitCurve equation + Gx, Gy *big.Int // (x,y) of the base point + BitSize int // the size of the underlying field +} + +func (BitCurve *BitCurve) Params() *elliptic.CurveParams { + return &elliptic.CurveParams{ + P: BitCurve.P, + N: BitCurve.N, + B: BitCurve.B, + Gx: BitCurve.Gx, + Gy: BitCurve.Gy, + BitSize: BitCurve.BitSize, + } +} + +// IsOnBitCurve returns true if the given (x,y) lies on the BitCurve. +func (BitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool { + // y² = x³ + b + y2 := new(big.Int).Mul(y, y) //y² + y2.Mod(y2, BitCurve.P) //y²%P + + x3 := new(big.Int).Mul(x, x) //x² + x3.Mul(x3, x) //x³ + + x3.Add(x3, BitCurve.B) //x³+B + x3.Mod(x3, BitCurve.P) //(x³+B)%P + + return x3.Cmp(y2) == 0 +} + +//TODO: double check if the function is okay +// affineFromJacobian reverses the Jacobian transform. See the comment at the +// top of the file. +func (BitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) { + zinv := new(big.Int).ModInverse(z, BitCurve.P) + zinvsq := new(big.Int).Mul(zinv, zinv) + + xOut = new(big.Int).Mul(x, zinvsq) + xOut.Mod(xOut, BitCurve.P) + zinvsq.Mul(zinvsq, zinv) + yOut = new(big.Int).Mul(y, zinvsq) + yOut.Mod(yOut, BitCurve.P) + return +} + +// Add returns the sum of (x1,y1) and (x2,y2) +func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { + z := new(big.Int).SetInt64(1) + return BitCurve.affineFromJacobian(BitCurve.addJacobian(x1, y1, z, x2, y2, z)) +} + +// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and +// (x2, y2, z2) and returns their sum, also in Jacobian form. +func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { + // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl + z1z1 := new(big.Int).Mul(z1, z1) + z1z1.Mod(z1z1, BitCurve.P) + z2z2 := new(big.Int).Mul(z2, z2) + z2z2.Mod(z2z2, BitCurve.P) + + u1 := new(big.Int).Mul(x1, z2z2) + u1.Mod(u1, BitCurve.P) + u2 := new(big.Int).Mul(x2, z1z1) + u2.Mod(u2, BitCurve.P) + h := new(big.Int).Sub(u2, u1) + if h.Sign() == -1 { + h.Add(h, BitCurve.P) + } + i := new(big.Int).Lsh(h, 1) + i.Mul(i, i) + j := new(big.Int).Mul(h, i) + + s1 := new(big.Int).Mul(y1, z2) + s1.Mul(s1, z2z2) + s1.Mod(s1, BitCurve.P) + s2 := new(big.Int).Mul(y2, z1) + s2.Mul(s2, z1z1) + s2.Mod(s2, BitCurve.P) + r := new(big.Int).Sub(s2, s1) + if r.Sign() == -1 { + r.Add(r, BitCurve.P) + } + r.Lsh(r, 1) + v := new(big.Int).Mul(u1, i) + + x3 := new(big.Int).Set(r) + x3.Mul(x3, x3) + x3.Sub(x3, j) + x3.Sub(x3, v) + x3.Sub(x3, v) + x3.Mod(x3, BitCurve.P) + + y3 := new(big.Int).Set(r) + v.Sub(v, x3) + y3.Mul(y3, v) + s1.Mul(s1, j) + s1.Lsh(s1, 1) + y3.Sub(y3, s1) + y3.Mod(y3, BitCurve.P) + + z3 := new(big.Int).Add(z1, z2) + z3.Mul(z3, z3) + z3.Sub(z3, z1z1) + if z3.Sign() == -1 { + z3.Add(z3, BitCurve.P) + } + z3.Sub(z3, z2z2) + if z3.Sign() == -1 { + z3.Add(z3, BitCurve.P) + } + z3.Mul(z3, h) + z3.Mod(z3, BitCurve.P) + + return x3, y3, z3 +} + +// Double returns 2*(x,y) +func (BitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { + z1 := new(big.Int).SetInt64(1) + return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z1)) +} + +// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and +// returns its double, also in Jacobian form. +func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { + // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + + a := new(big.Int).Mul(x, x) //X1² + b := new(big.Int).Mul(y, y) //Y1² + c := new(big.Int).Mul(b, b) //B² + + d := new(big.Int).Add(x, b) //X1+B + d.Mul(d, d) //(X1+B)² + d.Sub(d, a) //(X1+B)²-A + d.Sub(d, c) //(X1+B)²-A-C + d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C) + + e := new(big.Int).Mul(big.NewInt(3), a) //3*A + f := new(big.Int).Mul(e, e) //E² + + x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D + x3.Sub(f, x3) //F-2*D + x3.Mod(x3, BitCurve.P) + + y3 := new(big.Int).Sub(d, x3) //D-X3 + y3.Mul(e, y3) //E*(D-X3) + y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C + y3.Mod(y3, BitCurve.P) + + z3 := new(big.Int).Mul(y, z) //Y1*Z1 + z3.Mul(big.NewInt(2), z3) //3*Y1*Z1 + z3.Mod(z3, BitCurve.P) + + return x3, y3, z3 +} + +func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) { + // Ensure scalar is exactly 32 bytes. We pad always, even if + // scalar is 32 bytes long, to avoid a timing side channel. + if len(scalar) > 32 { + panic("can't handle scalars > 256 bits") + } + // NOTE: potential timing issue + padded := make([]byte, 32) + copy(padded[32-len(scalar):], scalar) + scalar = padded + + // Do the multiplication in C, updating point. + point := make([]byte, 64) + math.ReadBits(Bx, point[:32]) + math.ReadBits(By, point[32:]) + pointPtr := (*C.uchar)(unsafe.Pointer(&point[0])) + scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0])) + res := C.secp256k1_pubkey_scalar_mul(context, pointPtr, scalarPtr) + + // Unpack the result and clear temporaries. + x := new(big.Int).SetBytes(point[:32]) + y := new(big.Int).SetBytes(point[32:]) + for i := range point { + point[i] = 0 + } + for i := range padded { + scalar[i] = 0 + } + if res != 1 { + return nil, nil + } + return x, y +} + +// ScalarBaseMult returns k*G, where G is the base point of the group and k is +// an integer in big-endian form. +func (BitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { + return BitCurve.ScalarMult(BitCurve.Gx, BitCurve.Gy, k) +} + +// Marshal converts a point into the form specified in section 4.3.6 of ANSI +// X9.62. +func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte { + byteLen := (BitCurve.BitSize + 7) >> 3 + + ret := make([]byte, 1+2*byteLen) + ret[0] = 4 // uncompressed point + + xBytes := x.Bytes() + copy(ret[1+byteLen-len(xBytes):], xBytes) + yBytes := y.Bytes() + copy(ret[1+2*byteLen-len(yBytes):], yBytes) + return ret +} + +// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On +// error, x = nil. +func (BitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) { + byteLen := (BitCurve.BitSize + 7) >> 3 + if len(data) != 1+2*byteLen { + return + } + if data[0] != 4 { // uncompressed form + return + } + x = new(big.Int).SetBytes(data[1 : 1+byteLen]) + y = new(big.Int).SetBytes(data[1+byteLen:]) + return +} + +var ( + initonce sync.Once + theCurve *BitCurve +) + +// S256 returns a BitCurve which implements secp256k1 (see SEC 2 section 2.7.1) +func S256() *BitCurve { + initonce.Do(func() { + // See SEC 2 section 2.7.1 + // curve parameters taken from: + // http://www.secg.org/collateral/sec2_final.pdf + theCurve = new(BitCurve) + theCurve.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16) + theCurve.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16) + theCurve.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16) + theCurve.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16) + theCurve.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16) + theCurve.BitSize = 256 + }) + return theCurve +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/ext.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/ext.h new file mode 100644 index 00000000..ee759fde --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/ext.h @@ -0,0 +1,87 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// secp256k1_context_create_sign_verify creates a context for signing and signature verification. +static secp256k1_context* secp256k1_context_create_sign_verify() { + return secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); +} + +// secp256k1_ecdsa_recover_pubkey recovers the public key of an encoded compact signature. +// +// Returns: 1: recovery was successful +// 0: recovery was not successful +// Args: ctx: pointer to a context object (cannot be NULL) +// Out: pubkey_out: the serialized 65-byte public key of the signer (cannot be NULL) +// In: sigdata: pointer to a 65-byte signature with the recovery id at the end (cannot be NULL) +// msgdata: pointer to a 32-byte message (cannot be NULL) +static int secp256k1_ecdsa_recover_pubkey( + const secp256k1_context* ctx, + unsigned char *pubkey_out, + const unsigned char *sigdata, + const unsigned char *msgdata +) { + secp256k1_ecdsa_recoverable_signature sig; + secp256k1_pubkey pubkey; + + if (!secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &sig, sigdata, (int)sigdata[64])) { + return 0; + } + if (!secp256k1_ecdsa_recover(ctx, &pubkey, &sig, msgdata)) { + return 0; + } + size_t outputlen = 65; + return secp256k1_ec_pubkey_serialize(ctx, pubkey_out, &outputlen, &pubkey, SECP256K1_EC_UNCOMPRESSED); +} + +// secp256k1_pubkey_scalar_mul multiplies a point by a scalar in constant time. +// +// Returns: 1: multiplication was successful +// 0: scalar was invalid (zero or overflow) +// Args: ctx: pointer to a context object (cannot be NULL) +// Out: point: the multiplied point (usually secret) +// In: point: pointer to a 64-byte public point, +// encoded as two 256bit big-endian numbers. +// scalar: a 32-byte scalar with which to multiply the point +int secp256k1_pubkey_scalar_mul(const secp256k1_context* ctx, unsigned char *point, const unsigned char *scalar) { + int ret = 0; + int overflow = 0; + secp256k1_fe feX, feY; + secp256k1_gej res; + secp256k1_ge ge; + secp256k1_scalar s; + ARG_CHECK(point != NULL); + ARG_CHECK(scalar != NULL); + (void)ctx; + + secp256k1_fe_set_b32(&feX, point); + secp256k1_fe_set_b32(&feY, point+32); + secp256k1_ge_set_xy(&ge, &feX, &feY); + secp256k1_scalar_set_b32(&s, scalar, &overflow); + if (overflow || secp256k1_scalar_is_zero(&s)) { + ret = 0; + } else { + secp256k1_ecmult_const(&res, &ge, &s); + secp256k1_ge_set_gej(&ge, &res); + /* Note: can't use secp256k1_pubkey_save here because it is not constant time. */ + secp256k1_fe_normalize(&ge.x); + secp256k1_fe_normalize(&ge.y); + secp256k1_fe_get_b32(point, &ge.x); + secp256k1_fe_get_b32(point+32, &ge.y); + ret = 1; + } + secp256k1_scalar_clear(&s); + return ret; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore new file mode 100644 index 00000000..87fea161 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.gitignore @@ -0,0 +1,49 @@ +bench_inv +bench_ecdh +bench_sign +bench_verify +bench_schnorr_verify +bench_recover +bench_internal +tests +exhaustive_tests +gen_context +*.exe +*.so +*.a +!.gitignore + +Makefile +configure +.libs/ +Makefile.in +aclocal.m4 +autom4te.cache/ +config.log +config.status +*.tar.gz +*.la +libtool +.deps/ +.dirstamp +*.lo +*.o +*~ +src/libsecp256k1-config.h +src/libsecp256k1-config.h.in +src/ecmult_static_context.h +build-aux/config.guess +build-aux/config.sub +build-aux/depcomp +build-aux/install-sh +build-aux/ltmain.sh +build-aux/m4/libtool.m4 +build-aux/m4/lt~obsolete.m4 +build-aux/m4/ltoptions.m4 +build-aux/m4/ltsugar.m4 +build-aux/m4/ltversion.m4 +build-aux/missing +build-aux/compile +build-aux/test-driver +src/stamp-h1 +libsecp256k1.pc diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml new file mode 100644 index 00000000..24395292 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/.travis.yml @@ -0,0 +1,69 @@ +language: c +sudo: false +addons: + apt: + packages: libgmp-dev +compiler: + - clang + - gcc +cache: + directories: + - src/java/guava/ +env: + global: + - FIELD=auto BIGNUM=auto SCALAR=auto ENDOMORPHISM=no STATICPRECOMPUTATION=yes ASM=no BUILD=check EXTRAFLAGS= HOST= ECDH=no RECOVERY=no EXPERIMENTAL=no + - GUAVA_URL=https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar GUAVA_JAR=src/java/guava/guava-18.0.jar + matrix: + - SCALAR=32bit RECOVERY=yes + - SCALAR=32bit FIELD=32bit ECDH=yes EXPERIMENTAL=yes + - SCALAR=64bit + - FIELD=64bit RECOVERY=yes + - FIELD=64bit ENDOMORPHISM=yes + - FIELD=64bit ENDOMORPHISM=yes ECDH=yes EXPERIMENTAL=yes + - FIELD=64bit ASM=x86_64 + - FIELD=64bit ENDOMORPHISM=yes ASM=x86_64 + - FIELD=32bit ENDOMORPHISM=yes + - BIGNUM=no + - BIGNUM=no ENDOMORPHISM=yes RECOVERY=yes EXPERIMENTAL=yes + - BIGNUM=no STATICPRECOMPUTATION=no + - BUILD=distcheck + - EXTRAFLAGS=CPPFLAGS=-DDETERMINISTIC + - EXTRAFLAGS=CFLAGS=-O0 + - BUILD=check-java ECDH=yes EXPERIMENTAL=yes +matrix: + fast_finish: true + include: + - compiler: clang + env: HOST=i686-linux-gnu ENDOMORPHISM=yes + addons: + apt: + packages: + - gcc-multilib + - libgmp-dev:i386 + - compiler: clang + env: HOST=i686-linux-gnu + addons: + apt: + packages: + - gcc-multilib + - compiler: gcc + env: HOST=i686-linux-gnu ENDOMORPHISM=yes + addons: + apt: + packages: + - gcc-multilib + - compiler: gcc + env: HOST=i686-linux-gnu + addons: + apt: + packages: + - gcc-multilib + - libgmp-dev:i386 +before_install: mkdir -p `dirname $GUAVA_JAR` +install: if [ ! -f $GUAVA_JAR ]; then wget $GUAVA_URL -O $GUAVA_JAR; fi +before_script: ./autogen.sh +script: + - if [ -n "$HOST" ]; then export USE_HOST="--host=$HOST"; fi + - if [ "x$HOST" = "xi686-linux-gnu" ]; then export CC="$CC -m32"; fi + - ./configure --enable-experimental=$EXPERIMENTAL --enable-endomorphism=$ENDOMORPHISM --with-field=$FIELD --with-bignum=$BIGNUM --with-scalar=$SCALAR --enable-ecmult-static-precomputation=$STATICPRECOMPUTATION --enable-module-ecdh=$ECDH --enable-module-recovery=$RECOVERY $EXTRAFLAGS $USE_HOST && make -j2 $BUILD +os: linux diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING new file mode 100644 index 00000000..4522a599 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/COPYING @@ -0,0 +1,19 @@ +Copyright (c) 2013 Pieter Wuille + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am new file mode 100644 index 00000000..c071fbe2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/Makefile.am @@ -0,0 +1,177 @@ +ACLOCAL_AMFLAGS = -I build-aux/m4 + +lib_LTLIBRARIES = libsecp256k1.la +if USE_JNI +JNI_LIB = libsecp256k1_jni.la +noinst_LTLIBRARIES = $(JNI_LIB) +else +JNI_LIB = +endif +include_HEADERS = include/secp256k1.h +noinst_HEADERS = +noinst_HEADERS += src/scalar.h +noinst_HEADERS += src/scalar_4x64.h +noinst_HEADERS += src/scalar_8x32.h +noinst_HEADERS += src/scalar_low.h +noinst_HEADERS += src/scalar_impl.h +noinst_HEADERS += src/scalar_4x64_impl.h +noinst_HEADERS += src/scalar_8x32_impl.h +noinst_HEADERS += src/scalar_low_impl.h +noinst_HEADERS += src/group.h +noinst_HEADERS += src/group_impl.h +noinst_HEADERS += src/num_gmp.h +noinst_HEADERS += src/num_gmp_impl.h +noinst_HEADERS += src/ecdsa.h +noinst_HEADERS += src/ecdsa_impl.h +noinst_HEADERS += src/eckey.h +noinst_HEADERS += src/eckey_impl.h +noinst_HEADERS += src/ecmult.h +noinst_HEADERS += src/ecmult_impl.h +noinst_HEADERS += src/ecmult_const.h +noinst_HEADERS += src/ecmult_const_impl.h +noinst_HEADERS += src/ecmult_gen.h +noinst_HEADERS += src/ecmult_gen_impl.h +noinst_HEADERS += src/num.h +noinst_HEADERS += src/num_impl.h +noinst_HEADERS += src/field_10x26.h +noinst_HEADERS += src/field_10x26_impl.h +noinst_HEADERS += src/field_5x52.h +noinst_HEADERS += src/field_5x52_impl.h +noinst_HEADERS += src/field_5x52_int128_impl.h +noinst_HEADERS += src/field_5x52_asm_impl.h +noinst_HEADERS += src/java/org_bitcoin_NativeSecp256k1.h +noinst_HEADERS += src/java/org_bitcoin_Secp256k1Context.h +noinst_HEADERS += src/util.h +noinst_HEADERS += src/testrand.h +noinst_HEADERS += src/testrand_impl.h +noinst_HEADERS += src/hash.h +noinst_HEADERS += src/hash_impl.h +noinst_HEADERS += src/field.h +noinst_HEADERS += src/field_impl.h +noinst_HEADERS += src/bench.h +noinst_HEADERS += contrib/lax_der_parsing.h +noinst_HEADERS += contrib/lax_der_parsing.c +noinst_HEADERS += contrib/lax_der_privatekey_parsing.h +noinst_HEADERS += contrib/lax_der_privatekey_parsing.c + +if USE_EXTERNAL_ASM +COMMON_LIB = libsecp256k1_common.la +noinst_LTLIBRARIES = $(COMMON_LIB) +else +COMMON_LIB = +endif + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libsecp256k1.pc + +if USE_EXTERNAL_ASM +if USE_ASM_ARM +libsecp256k1_common_la_SOURCES = src/asm/field_10x26_arm.s +endif +endif + +libsecp256k1_la_SOURCES = src/secp256k1.c +libsecp256k1_la_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/include -I$(top_srcdir)/src $(SECP_INCLUDES) +libsecp256k1_la_LIBADD = $(JNI_LIB) $(SECP_LIBS) $(COMMON_LIB) + +libsecp256k1_jni_la_SOURCES = src/java/org_bitcoin_NativeSecp256k1.c src/java/org_bitcoin_Secp256k1Context.c +libsecp256k1_jni_la_CPPFLAGS = -DSECP256K1_BUILD $(JNI_INCLUDES) + +noinst_PROGRAMS = +if USE_BENCHMARK +noinst_PROGRAMS += bench_verify bench_sign bench_internal +bench_verify_SOURCES = src/bench_verify.c +bench_verify_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +bench_sign_SOURCES = src/bench_sign.c +bench_sign_LDADD = libsecp256k1.la $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +bench_internal_SOURCES = src/bench_internal.c +bench_internal_LDADD = $(SECP_LIBS) $(COMMON_LIB) +bench_internal_CPPFLAGS = -DSECP256K1_BUILD $(SECP_INCLUDES) +endif + +TESTS = +if USE_TESTS +noinst_PROGRAMS += tests +tests_SOURCES = src/tests.c +tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src -I$(top_srcdir)/include $(SECP_INCLUDES) $(SECP_TEST_INCLUDES) +if !ENABLE_COVERAGE +tests_CPPFLAGS += -DVERIFY +endif +tests_LDADD = $(SECP_LIBS) $(SECP_TEST_LIBS) $(COMMON_LIB) +tests_LDFLAGS = -static +TESTS += tests +endif + +if USE_EXHAUSTIVE_TESTS +noinst_PROGRAMS += exhaustive_tests +exhaustive_tests_SOURCES = src/tests_exhaustive.c +exhaustive_tests_CPPFLAGS = -DSECP256K1_BUILD -I$(top_srcdir)/src $(SECP_INCLUDES) +if !ENABLE_COVERAGE +exhaustive_tests_CPPFLAGS += -DVERIFY +endif +exhaustive_tests_LDADD = $(SECP_LIBS) +exhaustive_tests_LDFLAGS = -static +TESTS += exhaustive_tests +endif + +JAVAROOT=src/java +JAVAORG=org/bitcoin +JAVA_GUAVA=$(srcdir)/$(JAVAROOT)/guava/guava-18.0.jar +CLASSPATH_ENV=CLASSPATH=$(JAVA_GUAVA) +JAVA_FILES= \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1.java \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Test.java \ + $(JAVAROOT)/$(JAVAORG)/NativeSecp256k1Util.java \ + $(JAVAROOT)/$(JAVAORG)/Secp256k1Context.java + +if USE_JNI + +$(JAVA_GUAVA): + @echo Guava is missing. Fetch it via: \ + wget https://search.maven.org/remotecontent?filepath=com/google/guava/guava/18.0/guava-18.0.jar -O $(@) + @false + +.stamp-java: $(JAVA_FILES) + @echo Compiling $^ + $(AM_V_at)$(CLASSPATH_ENV) javac $^ + @touch $@ + +if USE_TESTS + +check-java: libsecp256k1.la $(JAVA_GUAVA) .stamp-java + $(AM_V_at)java -Djava.library.path="./:./src:./src/.libs:.libs/" -cp "$(JAVA_GUAVA):$(JAVAROOT)" $(JAVAORG)/NativeSecp256k1Test + +endif +endif + +if USE_ECMULT_STATIC_PRECOMPUTATION +CPPFLAGS_FOR_BUILD +=-I$(top_srcdir) +CFLAGS_FOR_BUILD += -Wall -Wextra -Wno-unused-function + +gen_context_OBJECTS = gen_context.o +gen_context_BIN = gen_context$(BUILD_EXEEXT) +gen_%.o: src/gen_%.c + $(CC_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) -c $< -o $@ + +$(gen_context_BIN): $(gen_context_OBJECTS) + $(CC_FOR_BUILD) $^ -o $@ + +$(libsecp256k1_la_OBJECTS): src/ecmult_static_context.h +$(tests_OBJECTS): src/ecmult_static_context.h +$(bench_internal_OBJECTS): src/ecmult_static_context.h + +src/ecmult_static_context.h: $(gen_context_BIN) + ./$(gen_context_BIN) + +CLEANFILES = $(gen_context_BIN) src/ecmult_static_context.h $(JAVAROOT)/$(JAVAORG)/*.class .stamp-java +endif + +EXTRA_DIST = autogen.sh src/gen_context.c src/basic-config.h $(JAVA_FILES) + +if ENABLE_MODULE_ECDH +include src/modules/ecdh/Makefile.am.include +endif + +if ENABLE_MODULE_RECOVERY +include src/modules/recovery/Makefile.am.include +endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md new file mode 100644 index 00000000..8cd344ea --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/README.md @@ -0,0 +1,61 @@ +libsecp256k1 +============ + +[![Build Status](https://travis-ci.org/bitcoin-core/secp256k1.svg?branch=master)](https://travis-ci.org/bitcoin-core/secp256k1) + +Optimized C library for EC operations on curve secp256k1. + +This library is a work in progress and is being used to research best practices. Use at your own risk. + +Features: +* secp256k1 ECDSA signing/verification and key generation. +* Adding/multiplying private/public keys. +* Serialization/parsing of private keys, public keys, signatures. +* Constant time, constant memory access signing and pubkey generation. +* Derandomized DSA (via RFC6979 or with a caller provided function.) +* Very efficient implementation. + +Implementation details +---------------------- + +* General + * No runtime heap allocation. + * Extensive testing infrastructure. + * Structured to facilitate review and analysis. + * Intended to be portable to any system with a C89 compiler and uint64_t support. + * Expose only higher level interfaces to minimize the API surface and improve application security. ("Be difficult to use insecurely.") +* Field operations + * Optimized implementation of arithmetic modulo the curve's field size (2^256 - 0x1000003D1). + * Using 5 52-bit limbs (including hand-optimized assembly for x86_64, by Diederik Huys). + * Using 10 26-bit limbs. + * Field inverses and square roots using a sliding window over blocks of 1s (by Peter Dettman). +* Scalar operations + * Optimized implementation without data-dependent branches of arithmetic modulo the curve's order. + * Using 4 64-bit limbs (relying on __int128 support in the compiler). + * Using 8 32-bit limbs. +* Group operations + * Point addition formula specifically simplified for the curve equation (y^2 = x^3 + 7). + * Use addition between points in Jacobian and affine coordinates where possible. + * Use a unified addition/doubling formula where necessary to avoid data-dependent branches. + * Point/x comparison without a field inversion by comparison in the Jacobian coordinate space. +* Point multiplication for verification (a*P + b*G). + * Use wNAF notation for point multiplicands. + * Use a much larger window for multiples of G, using precomputed multiples. + * Use Shamir's trick to do the multiplication with the public key and the generator simultaneously. + * Optionally (off by default) use secp256k1's efficiently-computable endomorphism to split the P multiplicand into 2 half-sized ones. +* Point multiplication for signing + * Use a precomputed table of multiples of powers of 16 multiplied with the generator, so general multiplication becomes a series of additions. + * Access the table with branch-free conditional moves so memory access is uniform. + * No data-dependent branches + * The precomputed tables add and eventually subtract points for which no known scalar (private key) is known, preventing even an attacker with control over the private key used to control the data internally. + +Build steps +----------- + +libsecp256k1 is built using autotools: + + $ ./autogen.sh + $ ./configure + $ make + $ ./tests + $ sudo make install # optional diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO new file mode 100644 index 00000000..a300e1c5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/TODO @@ -0,0 +1,3 @@ +* Unit tests for fieldelem/groupelem, including ones intended to + trigger fieldelem's boundary cases. +* Complete constant-time operations for signing/keygen diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh new file mode 100755 index 00000000..65286b93 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/autogen.sh @@ -0,0 +1,3 @@ +#!/bin/sh +set -e +autoreconf -if --warnings=all diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 new file mode 100644 index 00000000..1fc36276 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_jni_include_dir.m4 @@ -0,0 +1,140 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_JNI_INCLUDE_DIR +# +# DESCRIPTION +# +# AX_JNI_INCLUDE_DIR finds include directories needed for compiling +# programs using the JNI interface. +# +# JNI include directories are usually in the Java distribution. This is +# deduced from the value of $JAVA_HOME, $JAVAC, or the path to "javac", in +# that order. When this macro completes, a list of directories is left in +# the variable JNI_INCLUDE_DIRS. +# +# Example usage follows: +# +# AX_JNI_INCLUDE_DIR +# +# for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS +# do +# CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" +# done +# +# If you want to force a specific compiler: +# +# - at the configure.in level, set JAVAC=yourcompiler before calling +# AX_JNI_INCLUDE_DIR +# +# - at the configure level, setenv JAVAC +# +# Note: This macro can work with the autoconf M4 macros for Java programs. +# This particular macro is not part of the original set of macros. +# +# LICENSE +# +# Copyright (c) 2008 Don Anderson +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 10 + +AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) +AC_DEFUN([AX_JNI_INCLUDE_DIR],[ + +JNI_INCLUDE_DIRS="" + +if test "x$JAVA_HOME" != x; then + _JTOPDIR="$JAVA_HOME" +else + if test "x$JAVAC" = x; then + JAVAC=javac + fi + AC_PATH_PROG([_ACJNI_JAVAC], [$JAVAC], [no]) + if test "x$_ACJNI_JAVAC" = xno; then + AC_MSG_WARN([cannot find JDK; try setting \$JAVAC or \$JAVA_HOME]) + fi + _ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC") + _JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'` +fi + +case "$host_os" in + darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + _JINC="$_JTOPDIR/Headers";; + *) _JINC="$_JTOPDIR/include";; +esac +_AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) +_AS_ECHO_LOG([_JINC=$_JINC]) + +# On Mac OS X 10.6.4, jni.h is a symlink: +# /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h +# -> ../../CurrentJDK/Headers/jni.h. + +AC_CACHE_CHECK(jni headers, ac_cv_jni_header_path, +[ +if test -f "$_JINC/jni.h"; then + ac_cv_jni_header_path="$_JINC" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" +else + _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` + if test -f "$_JTOPDIR/include/jni.h"; then + ac_cv_jni_header_path="$_JTOPDIR/include" + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $ac_cv_jni_header_path" + else + ac_cv_jni_header_path=none + fi +fi +]) + + + +# get the likely subdirectories for system specific java includes +case "$host_os" in +bsdi*) _JNI_INC_SUBDIRS="bsdos";; +darwin*) _JNI_INC_SUBDIRS="darwin";; +freebsd*) _JNI_INC_SUBDIRS="freebsd";; +linux*) _JNI_INC_SUBDIRS="linux genunix";; +osf*) _JNI_INC_SUBDIRS="alpha";; +solaris*) _JNI_INC_SUBDIRS="solaris";; +mingw*) _JNI_INC_SUBDIRS="win32";; +cygwin*) _JNI_INC_SUBDIRS="win32";; +*) _JNI_INC_SUBDIRS="genunix";; +esac + +if test "x$ac_cv_jni_header_path" != "xnone"; then + # add any subdirectories that are present + for JINCSUBDIR in $_JNI_INC_SUBDIRS + do + if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" + fi + done +fi +]) + +# _ACJNI_FOLLOW_SYMLINKS +# Follows symbolic links on , +# finally setting variable _ACJNI_FOLLOWED +# ---------------------------------------- +AC_DEFUN([_ACJNI_FOLLOW_SYMLINKS],[ +# find the include directory relative to the javac executable +_cur="$1" +while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do + AC_MSG_CHECKING([symlink for $_cur]) + _slink=`ls -ld "$_cur" | sed 's/.* -> //'` + case "$_slink" in + /*) _cur="$_slink";; + # 'X' avoids triggering unwanted echo options. + *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; + esac + AC_MSG_RESULT([$_cur]) +done +_ACJNI_FOLLOWED="$_cur" +])# _ACJNI diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 new file mode 100644 index 00000000..77fd346a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/ax_prog_cc_for_build.m4 @@ -0,0 +1,125 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PROG_CC_FOR_BUILD +# +# DESCRIPTION +# +# This macro searches for a C compiler that generates native executables, +# that is a C compiler that surely is not a cross-compiler. This can be +# useful if you have to generate source code at compile-time like for +# example GCC does. +# +# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything +# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD). +# The value of these variables can be overridden by the user by specifying +# a compiler with an environment variable (like you do for standard CC). +# +# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object +# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if +# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are +# substituted in the Makefile. +# +# LICENSE +# +# Copyright (c) 2008 Paolo Bonzini +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 8 + +AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD]) +AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CPP])dnl +AC_REQUIRE([AC_EXEEXT])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl + +dnl Use the standard macros, but make them use other variable names +dnl +pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl +pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl +pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl +pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl +pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl +pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl +pushdef([ac_cv_objext], ac_cv_build_objext)dnl +pushdef([ac_exeext], ac_build_exeext)dnl +pushdef([ac_objext], ac_build_objext)dnl +pushdef([CC], CC_FOR_BUILD)dnl +pushdef([CPP], CPP_FOR_BUILD)dnl +pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl +pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl +pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl +pushdef([host], build)dnl +pushdef([host_alias], build_alias)dnl +pushdef([host_cpu], build_cpu)dnl +pushdef([host_vendor], build_vendor)dnl +pushdef([host_os], build_os)dnl +pushdef([ac_cv_host], ac_cv_build)dnl +pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl +pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl +pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl +pushdef([ac_cv_host_os], ac_cv_build_os)dnl +pushdef([ac_cpp], ac_build_cpp)dnl +pushdef([ac_compile], ac_build_compile)dnl +pushdef([ac_link], ac_build_link)dnl + +save_cross_compiling=$cross_compiling +save_ac_tool_prefix=$ac_tool_prefix +cross_compiling=no +ac_tool_prefix= + +AC_PROG_CC +AC_PROG_CPP +AC_EXEEXT + +ac_tool_prefix=$save_ac_tool_prefix +cross_compiling=$save_cross_compiling + +dnl Restore the old definitions +dnl +popdef([ac_link])dnl +popdef([ac_compile])dnl +popdef([ac_cpp])dnl +popdef([ac_cv_host_os])dnl +popdef([ac_cv_host_vendor])dnl +popdef([ac_cv_host_cpu])dnl +popdef([ac_cv_host_alias])dnl +popdef([ac_cv_host])dnl +popdef([host_os])dnl +popdef([host_vendor])dnl +popdef([host_cpu])dnl +popdef([host_alias])dnl +popdef([host])dnl +popdef([LDFLAGS])dnl +popdef([CPPFLAGS])dnl +popdef([CFLAGS])dnl +popdef([CPP])dnl +popdef([CC])dnl +popdef([ac_objext])dnl +popdef([ac_exeext])dnl +popdef([ac_cv_objext])dnl +popdef([ac_cv_exeext])dnl +popdef([ac_cv_prog_cc_g])dnl +popdef([ac_cv_prog_cc_cross])dnl +popdef([ac_cv_prog_cc_works])dnl +popdef([ac_cv_prog_gcc])dnl +popdef([ac_cv_prog_CPP])dnl + +dnl Finally, set Makefile variables +dnl +BUILD_EXEEXT=$ac_build_exeext +BUILD_OBJEXT=$ac_build_objext +AC_SUBST(BUILD_EXEEXT)dnl +AC_SUBST(BUILD_OBJEXT)dnl +AC_SUBST([CFLAGS_FOR_BUILD])dnl +AC_SUBST([CPPFLAGS_FOR_BUILD])dnl +AC_SUBST([LDFLAGS_FOR_BUILD])dnl +]) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 new file mode 100644 index 00000000..b74acb8c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/build-aux/m4/bitcoin_secp.m4 @@ -0,0 +1,69 @@ +dnl libsecp25k1 helper checks +AC_DEFUN([SECP_INT128_CHECK],[ +has_int128=$ac_cv_type___int128 +]) + +dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell. +AC_DEFUN([SECP_64BIT_ASM_CHECK],[ +AC_MSG_CHECKING(for x86_64 assembly availability) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include ]],[[ + uint64_t a = 11, tmp; + __asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx"); + ]])],[has_64bit_asm=yes],[has_64bit_asm=no]) +AC_MSG_RESULT([$has_64bit_asm]) +]) + +dnl +AC_DEFUN([SECP_OPENSSL_CHECK],[ + has_libcrypto=no + m4_ifdef([PKG_CHECK_MODULES],[ + PKG_CHECK_MODULES([CRYPTO], [libcrypto], [has_libcrypto=yes],[has_libcrypto=no]) + if test x"$has_libcrypto" = x"yes"; then + TEMP_LIBS="$LIBS" + LIBS="$LIBS $CRYPTO_LIBS" + AC_CHECK_LIB(crypto, main,[AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed])],[has_libcrypto=no]) + LIBS="$TEMP_LIBS" + fi + ]) + if test x$has_libcrypto = xno; then + AC_CHECK_HEADER(openssl/crypto.h,[ + AC_CHECK_LIB(crypto, main,[ + has_libcrypto=yes + CRYPTO_LIBS=-lcrypto + AC_DEFINE(HAVE_LIBCRYPTO,1,[Define this symbol if libcrypto is installed]) + ]) + ]) + LIBS= + fi +if test x"$has_libcrypto" = x"yes" && test x"$has_openssl_ec" = x; then + AC_MSG_CHECKING(for EC functions in libcrypto) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + #include ]],[[ + EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1); + ECDSA_sign(0, NULL, 0, NULL, NULL, eckey); + ECDSA_verify(0, NULL, 0, NULL, 0, eckey); + EC_KEY_free(eckey); + ECDSA_SIG *sig_openssl; + sig_openssl = ECDSA_SIG_new(); + (void)sig_openssl->r; + ECDSA_SIG_free(sig_openssl); + ]])],[has_openssl_ec=yes],[has_openssl_ec=no]) + AC_MSG_RESULT([$has_openssl_ec]) +fi +]) + +dnl +AC_DEFUN([SECP_GMP_CHECK],[ +if test x"$has_gmp" != x"yes"; then + CPPFLAGS_TEMP="$CPPFLAGS" + CPPFLAGS="$GMP_CPPFLAGS $CPPFLAGS" + LIBS_TEMP="$LIBS" + LIBS="$GMP_LIBS $LIBS" + AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; GMP_LIBS="$GMP_LIBS -lgmp"; AC_DEFINE(HAVE_LIBGMP,1,[Define this symbol if libgmp is installed])])]) + CPPFLAGS="$CPPFLAGS_TEMP" + LIBS="$LIBS_TEMP" +fi +]) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac new file mode 100644 index 00000000..e5fcbcb4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/configure.ac @@ -0,0 +1,493 @@ +AC_PREREQ([2.60]) +AC_INIT([libsecp256k1],[0.1]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([build-aux/m4]) +AC_CANONICAL_HOST +AH_TOP([#ifndef LIBSECP256K1_CONFIG_H]) +AH_TOP([#define LIBSECP256K1_CONFIG_H]) +AH_BOTTOM([#endif /*LIBSECP256K1_CONFIG_H*/]) +AM_INIT_AUTOMAKE([foreign subdir-objects]) +LT_INIT + +dnl make the compilation flags quiet unless V=1 is used +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +PKG_PROG_PKG_CONFIG + +AC_PATH_TOOL(AR, ar) +AC_PATH_TOOL(RANLIB, ranlib) +AC_PATH_TOOL(STRIP, strip) +AX_PROG_CC_FOR_BUILD + +if test "x$CFLAGS" = "x"; then + CFLAGS="-g" +fi + +AM_PROG_CC_C_O + +AC_PROG_CC_C89 +if test x"$ac_cv_prog_cc_c89" = x"no"; then + AC_MSG_ERROR([c89 compiler support required]) +fi +AM_PROG_AS + +case $host_os in + *darwin*) + if test x$cross_compiling != xyes; then + AC_PATH_PROG([BREW],brew,) + if test x$BREW != x; then + dnl These Homebrew packages may be keg-only, meaning that they won't be found + dnl in expected paths because they may conflict with system files. Ask + dnl Homebrew where each one is located, then adjust paths accordingly. + + openssl_prefix=`$BREW --prefix openssl 2>/dev/null` + gmp_prefix=`$BREW --prefix gmp 2>/dev/null` + if test x$openssl_prefix != x; then + PKG_CONFIG_PATH="$openssl_prefix/lib/pkgconfig:$PKG_CONFIG_PATH" + export PKG_CONFIG_PATH + fi + if test x$gmp_prefix != x; then + GMP_CPPFLAGS="-I$gmp_prefix/include" + GMP_LIBS="-L$gmp_prefix/lib" + fi + else + AC_PATH_PROG([PORT],port,) + dnl if homebrew isn't installed and macports is, add the macports default paths + dnl as a last resort. + if test x$PORT != x; then + CPPFLAGS="$CPPFLAGS -isystem /opt/local/include" + LDFLAGS="$LDFLAGS -L/opt/local/lib" + fi + fi + fi + ;; +esac + +CFLAGS="$CFLAGS -W" + +warn_CFLAGS="-std=c89 -pedantic -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wstrict-prototypes -Wno-unused-function -Wno-long-long -Wno-overlength-strings" +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $warn_CFLAGS" +AC_MSG_CHECKING([if ${CC} supports ${warn_CFLAGS}]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], + [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" + ]) + +saved_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -fvisibility=hidden" +AC_MSG_CHECKING([if ${CC} supports -fvisibility=hidden]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])], + [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_RESULT([no]) + CFLAGS="$saved_CFLAGS" + ]) + +AC_ARG_ENABLE(benchmark, + AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]), + [use_benchmark=$enableval], + [use_benchmark=no]) + +AC_ARG_ENABLE(coverage, + AS_HELP_STRING([--enable-coverage],[enable compiler flags to support kcov coverage analysis]), + [enable_coverage=$enableval], + [enable_coverage=no]) + +AC_ARG_ENABLE(tests, + AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), + [use_tests=$enableval], + [use_tests=yes]) + +AC_ARG_ENABLE(openssl_tests, + AS_HELP_STRING([--enable-openssl-tests],[enable OpenSSL tests, if OpenSSL is available (default is auto)]), + [enable_openssl_tests=$enableval], + [enable_openssl_tests=auto]) + +AC_ARG_ENABLE(experimental, + AS_HELP_STRING([--enable-experimental],[allow experimental configure options (default is no)]), + [use_experimental=$enableval], + [use_experimental=no]) + +AC_ARG_ENABLE(exhaustive_tests, + AS_HELP_STRING([--enable-exhaustive-tests],[compile exhaustive tests (default is yes)]), + [use_exhaustive_tests=$enableval], + [use_exhaustive_tests=yes]) + +AC_ARG_ENABLE(endomorphism, + AS_HELP_STRING([--enable-endomorphism],[enable endomorphism (default is no)]), + [use_endomorphism=$enableval], + [use_endomorphism=no]) + +AC_ARG_ENABLE(ecmult_static_precomputation, + AS_HELP_STRING([--enable-ecmult-static-precomputation],[enable precomputed ecmult table for signing (default is yes)]), + [use_ecmult_static_precomputation=$enableval], + [use_ecmult_static_precomputation=auto]) + +AC_ARG_ENABLE(module_ecdh, + AS_HELP_STRING([--enable-module-ecdh],[enable ECDH shared secret computation (experimental)]), + [enable_module_ecdh=$enableval], + [enable_module_ecdh=no]) + +AC_ARG_ENABLE(module_recovery, + AS_HELP_STRING([--enable-module-recovery],[enable ECDSA pubkey recovery module (default is no)]), + [enable_module_recovery=$enableval], + [enable_module_recovery=no]) + +AC_ARG_ENABLE(jni, + AS_HELP_STRING([--enable-jni],[enable libsecp256k1_jni (default is auto)]), + [use_jni=$enableval], + [use_jni=auto]) + +AC_ARG_WITH([field], [AS_HELP_STRING([--with-field=64bit|32bit|auto], +[Specify Field Implementation. Default is auto])],[req_field=$withval], [req_field=auto]) + +AC_ARG_WITH([bignum], [AS_HELP_STRING([--with-bignum=gmp|no|auto], +[Specify Bignum Implementation. Default is auto])],[req_bignum=$withval], [req_bignum=auto]) + +AC_ARG_WITH([scalar], [AS_HELP_STRING([--with-scalar=64bit|32bit|auto], +[Specify scalar implementation. Default is auto])],[req_scalar=$withval], [req_scalar=auto]) + +AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto] +[Specify assembly optimizations to use. Default is auto (experimental: arm)])],[req_asm=$withval], [req_asm=auto]) + +AC_CHECK_TYPES([__int128]) + +AC_MSG_CHECKING([for __builtin_expect]) +AC_COMPILE_IFELSE([AC_LANG_SOURCE([[void myfunc() {__builtin_expect(0,0);}]])], + [ AC_MSG_RESULT([yes]);AC_DEFINE(HAVE_BUILTIN_EXPECT,1,[Define this symbol if __builtin_expect is available]) ], + [ AC_MSG_RESULT([no]) + ]) + +if test x"$enable_coverage" = x"yes"; then + AC_DEFINE(COVERAGE, 1, [Define this symbol to compile out all VERIFY code]) + CFLAGS="$CFLAGS -O0 --coverage" + LDFLAGS="--coverage" +else + CFLAGS="$CFLAGS -O3" +fi + +if test x"$use_ecmult_static_precomputation" != x"no"; then + save_cross_compiling=$cross_compiling + cross_compiling=no + TEMP_CC="$CC" + CC="$CC_FOR_BUILD" + AC_MSG_CHECKING([native compiler: ${CC_FOR_BUILD}]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([], [return 0])], + [working_native_cc=yes], + [working_native_cc=no],[dnl]) + CC="$TEMP_CC" + cross_compiling=$save_cross_compiling + + if test x"$working_native_cc" = x"no"; then + set_precomp=no + if test x"$use_ecmult_static_precomputation" = x"yes"; then + AC_MSG_ERROR([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) + else + AC_MSG_RESULT([${CC_FOR_BUILD} does not produce working binaries. Please set CC_FOR_BUILD]) + fi + else + AC_MSG_RESULT([ok]) + set_precomp=yes + fi +else + set_precomp=no +fi + +if test x"$req_asm" = x"auto"; then + SECP_64BIT_ASM_CHECK + if test x"$has_64bit_asm" = x"yes"; then + set_asm=x86_64 + fi + if test x"$set_asm" = x; then + set_asm=no + fi +else + set_asm=$req_asm + case $set_asm in + x86_64) + SECP_64BIT_ASM_CHECK + if test x"$has_64bit_asm" != x"yes"; then + AC_MSG_ERROR([x86_64 assembly optimization requested but not available]) + fi + ;; + arm) + ;; + no) + ;; + *) + AC_MSG_ERROR([invalid assembly optimization selection]) + ;; + esac +fi + +if test x"$req_field" = x"auto"; then + if test x"set_asm" = x"x86_64"; then + set_field=64bit + fi + if test x"$set_field" = x; then + SECP_INT128_CHECK + if test x"$has_int128" = x"yes"; then + set_field=64bit + fi + fi + if test x"$set_field" = x; then + set_field=32bit + fi +else + set_field=$req_field + case $set_field in + 64bit) + if test x"$set_asm" != x"x86_64"; then + SECP_INT128_CHECK + if test x"$has_int128" != x"yes"; then + AC_MSG_ERROR([64bit field explicitly requested but neither __int128 support or x86_64 assembly available]) + fi + fi + ;; + 32bit) + ;; + *) + AC_MSG_ERROR([invalid field implementation selection]) + ;; + esac +fi + +if test x"$req_scalar" = x"auto"; then + SECP_INT128_CHECK + if test x"$has_int128" = x"yes"; then + set_scalar=64bit + fi + if test x"$set_scalar" = x; then + set_scalar=32bit + fi +else + set_scalar=$req_scalar + case $set_scalar in + 64bit) + SECP_INT128_CHECK + if test x"$has_int128" != x"yes"; then + AC_MSG_ERROR([64bit scalar explicitly requested but __int128 support not available]) + fi + ;; + 32bit) + ;; + *) + AC_MSG_ERROR([invalid scalar implementation selected]) + ;; + esac +fi + +if test x"$req_bignum" = x"auto"; then + SECP_GMP_CHECK + if test x"$has_gmp" = x"yes"; then + set_bignum=gmp + fi + + if test x"$set_bignum" = x; then + set_bignum=no + fi +else + set_bignum=$req_bignum + case $set_bignum in + gmp) + SECP_GMP_CHECK + if test x"$has_gmp" != x"yes"; then + AC_MSG_ERROR([gmp bignum explicitly requested but libgmp not available]) + fi + ;; + no) + ;; + *) + AC_MSG_ERROR([invalid bignum implementation selection]) + ;; + esac +fi + +# select assembly optimization +use_external_asm=no + +case $set_asm in +x86_64) + AC_DEFINE(USE_ASM_X86_64, 1, [Define this symbol to enable x86_64 assembly optimizations]) + ;; +arm) + use_external_asm=yes + ;; +no) + ;; +*) + AC_MSG_ERROR([invalid assembly optimizations]) + ;; +esac + +# select field implementation +case $set_field in +64bit) + AC_DEFINE(USE_FIELD_5X52, 1, [Define this symbol to use the FIELD_5X52 implementation]) + ;; +32bit) + AC_DEFINE(USE_FIELD_10X26, 1, [Define this symbol to use the FIELD_10X26 implementation]) + ;; +*) + AC_MSG_ERROR([invalid field implementation]) + ;; +esac + +# select bignum implementation +case $set_bignum in +gmp) + AC_DEFINE(HAVE_LIBGMP, 1, [Define this symbol if libgmp is installed]) + AC_DEFINE(USE_NUM_GMP, 1, [Define this symbol to use the gmp implementation for num]) + AC_DEFINE(USE_FIELD_INV_NUM, 1, [Define this symbol to use the num-based field inverse implementation]) + AC_DEFINE(USE_SCALAR_INV_NUM, 1, [Define this symbol to use the num-based scalar inverse implementation]) + ;; +no) + AC_DEFINE(USE_NUM_NONE, 1, [Define this symbol to use no num implementation]) + AC_DEFINE(USE_FIELD_INV_BUILTIN, 1, [Define this symbol to use the native field inverse implementation]) + AC_DEFINE(USE_SCALAR_INV_BUILTIN, 1, [Define this symbol to use the native scalar inverse implementation]) + ;; +*) + AC_MSG_ERROR([invalid bignum implementation]) + ;; +esac + +#select scalar implementation +case $set_scalar in +64bit) + AC_DEFINE(USE_SCALAR_4X64, 1, [Define this symbol to use the 4x64 scalar implementation]) + ;; +32bit) + AC_DEFINE(USE_SCALAR_8X32, 1, [Define this symbol to use the 8x32 scalar implementation]) + ;; +*) + AC_MSG_ERROR([invalid scalar implementation]) + ;; +esac + +if test x"$use_tests" = x"yes"; then + SECP_OPENSSL_CHECK + if test x"$has_openssl_ec" = x"yes"; then + if test x"$enable_openssl_tests" != x"no"; then + AC_DEFINE(ENABLE_OPENSSL_TESTS, 1, [Define this symbol if OpenSSL EC functions are available]) + SECP_TEST_INCLUDES="$SSL_CFLAGS $CRYPTO_CFLAGS" + SECP_TEST_LIBS="$CRYPTO_LIBS" + + case $host in + *mingw*) + SECP_TEST_LIBS="$SECP_TEST_LIBS -lgdi32" + ;; + esac + fi + else + if test x"$enable_openssl_tests" = x"yes"; then + AC_MSG_ERROR([OpenSSL tests requested but OpenSSL with EC support is not available]) + fi + fi +else + if test x"$enable_openssl_tests" = x"yes"; then + AC_MSG_ERROR([OpenSSL tests requested but tests are not enabled]) + fi +fi + +if test x"$use_jni" != x"no"; then + AX_JNI_INCLUDE_DIR + have_jni_dependencies=yes + if test x"$enable_module_ecdh" = x"no"; then + have_jni_dependencies=no + fi + if test "x$JNI_INCLUDE_DIRS" = "x"; then + have_jni_dependencies=no + fi + if test "x$have_jni_dependencies" = "xno"; then + if test x"$use_jni" = x"yes"; then + AC_MSG_ERROR([jni support explicitly requested but headers/dependencies were not found. Enable ECDH and try again.]) + fi + AC_MSG_WARN([jni headers/dependencies not found. jni support disabled]) + use_jni=no + else + use_jni=yes + for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do + JNI_INCLUDES="$JNI_INCLUDES -I$JNI_INCLUDE_DIR" + done + fi +fi + +if test x"$set_bignum" = x"gmp"; then + SECP_LIBS="$SECP_LIBS $GMP_LIBS" + SECP_INCLUDES="$SECP_INCLUDES $GMP_CPPFLAGS" +fi + +if test x"$use_endomorphism" = x"yes"; then + AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization]) +fi + +if test x"$set_precomp" = x"yes"; then + AC_DEFINE(USE_ECMULT_STATIC_PRECOMPUTATION, 1, [Define this symbol to use a statically generated ecmult table]) +fi + +if test x"$enable_module_ecdh" = x"yes"; then + AC_DEFINE(ENABLE_MODULE_ECDH, 1, [Define this symbol to enable the ECDH module]) +fi + +if test x"$enable_module_recovery" = x"yes"; then + AC_DEFINE(ENABLE_MODULE_RECOVERY, 1, [Define this symbol to enable the ECDSA pubkey recovery module]) +fi + +AC_C_BIGENDIAN() + +if test x"$use_external_asm" = x"yes"; then + AC_DEFINE(USE_EXTERNAL_ASM, 1, [Define this symbol if an external (non-inline) assembly implementation is used]) +fi + +AC_MSG_NOTICE([Using static precomputation: $set_precomp]) +AC_MSG_NOTICE([Using assembly optimizations: $set_asm]) +AC_MSG_NOTICE([Using field implementation: $set_field]) +AC_MSG_NOTICE([Using bignum implementation: $set_bignum]) +AC_MSG_NOTICE([Using scalar implementation: $set_scalar]) +AC_MSG_NOTICE([Using endomorphism optimizations: $use_endomorphism]) +AC_MSG_NOTICE([Building for coverage analysis: $enable_coverage]) +AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) +AC_MSG_NOTICE([Building ECDSA pubkey recovery module: $enable_module_recovery]) +AC_MSG_NOTICE([Using jni: $use_jni]) + +if test x"$enable_experimental" = x"yes"; then + AC_MSG_NOTICE([******]) + AC_MSG_NOTICE([WARNING: experimental build]) + AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.]) + AC_MSG_NOTICE([Building ECDH module: $enable_module_ecdh]) + AC_MSG_NOTICE([******]) +else + if test x"$enable_module_ecdh" = x"yes"; then + AC_MSG_ERROR([ECDH module is experimental. Use --enable-experimental to allow.]) + fi + if test x"$set_asm" = x"arm"; then + AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.]) + fi +fi + +AC_CONFIG_HEADERS([src/libsecp256k1-config.h]) +AC_CONFIG_FILES([Makefile libsecp256k1.pc]) +AC_SUBST(JNI_INCLUDES) +AC_SUBST(SECP_INCLUDES) +AC_SUBST(SECP_LIBS) +AC_SUBST(SECP_TEST_LIBS) +AC_SUBST(SECP_TEST_INCLUDES) +AM_CONDITIONAL([ENABLE_COVERAGE], [test x"$enable_coverage" = x"yes"]) +AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) +AM_CONDITIONAL([USE_EXHAUSTIVE_TESTS], [test x"$use_exhaustive_tests" != x"no"]) +AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) +AM_CONDITIONAL([USE_ECMULT_STATIC_PRECOMPUTATION], [test x"$set_precomp" = x"yes"]) +AM_CONDITIONAL([ENABLE_MODULE_ECDH], [test x"$enable_module_ecdh" = x"yes"]) +AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"yes"]) +AM_CONDITIONAL([USE_JNI], [test x"$use_jni" == x"yes"]) +AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$use_external_asm" = x"yes"]) +AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"]) + +dnl make sure nothing new is exported so that we don't break the cache +PKGCONFIG_PATH_TEMP="$PKG_CONFIG_PATH" +unset PKG_CONFIG_PATH +PKG_CONFIG_PATH="$PKGCONFIG_PATH_TEMP" + +AC_OUTPUT diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c new file mode 100644 index 00000000..5b141a99 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.c @@ -0,0 +1,150 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include + +#include "lax_der_parsing.h" + +int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { + size_t rpos, rlen, spos, slen; + size_t pos = 0; + size_t lenbyte; + unsigned char tmpsig[64] = {0}; + int overflow = 0; + + /* Hack to initialize sig with a correctly-parsed but invalid signature. */ + secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + + /* Sequence tag byte */ + if (pos == inputlen || input[pos] != 0x30) { + return 0; + } + pos++; + + /* Sequence length bytes */ + if (pos == inputlen) { + return 0; + } + lenbyte = input[pos++]; + if (lenbyte & 0x80) { + lenbyte -= 0x80; + if (pos + lenbyte > inputlen) { + return 0; + } + pos += lenbyte; + } + + /* Integer tag byte for R */ + if (pos == inputlen || input[pos] != 0x02) { + return 0; + } + pos++; + + /* Integer length for R */ + if (pos == inputlen) { + return 0; + } + lenbyte = input[pos++]; + if (lenbyte & 0x80) { + lenbyte -= 0x80; + if (pos + lenbyte > inputlen) { + return 0; + } + while (lenbyte > 0 && input[pos] == 0) { + pos++; + lenbyte--; + } + if (lenbyte >= sizeof(size_t)) { + return 0; + } + rlen = 0; + while (lenbyte > 0) { + rlen = (rlen << 8) + input[pos]; + pos++; + lenbyte--; + } + } else { + rlen = lenbyte; + } + if (rlen > inputlen - pos) { + return 0; + } + rpos = pos; + pos += rlen; + + /* Integer tag byte for S */ + if (pos == inputlen || input[pos] != 0x02) { + return 0; + } + pos++; + + /* Integer length for S */ + if (pos == inputlen) { + return 0; + } + lenbyte = input[pos++]; + if (lenbyte & 0x80) { + lenbyte -= 0x80; + if (pos + lenbyte > inputlen) { + return 0; + } + while (lenbyte > 0 && input[pos] == 0) { + pos++; + lenbyte--; + } + if (lenbyte >= sizeof(size_t)) { + return 0; + } + slen = 0; + while (lenbyte > 0) { + slen = (slen << 8) + input[pos]; + pos++; + lenbyte--; + } + } else { + slen = lenbyte; + } + if (slen > inputlen - pos) { + return 0; + } + spos = pos; + pos += slen; + + /* Ignore leading zeroes in R */ + while (rlen > 0 && input[rpos] == 0) { + rlen--; + rpos++; + } + /* Copy R value */ + if (rlen > 32) { + overflow = 1; + } else { + memcpy(tmpsig + 32 - rlen, input + rpos, rlen); + } + + /* Ignore leading zeroes in S */ + while (slen > 0 && input[spos] == 0) { + slen--; + spos++; + } + /* Copy S value */ + if (slen > 32) { + overflow = 1; + } else { + memcpy(tmpsig + 64 - slen, input + spos, slen); + } + + if (!overflow) { + overflow = !secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + } + if (overflow) { + memset(tmpsig, 0, 64); + secp256k1_ecdsa_signature_parse_compact(ctx, sig, tmpsig); + } + return 1; +} + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h new file mode 100644 index 00000000..6d27871a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_parsing.h @@ -0,0 +1,91 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +/**** + * Please do not link this file directly. It is not part of the libsecp256k1 + * project and does not promise any stability in its API, functionality or + * presence. Projects which use this code should instead copy this header + * and its accompanying .c file directly into their codebase. + ****/ + +/* This file defines a function that parses DER with various errors and + * violations. This is not a part of the library itself, because the allowed + * violations are chosen arbitrarily and do not follow or establish any + * standard. + * + * In many places it matters that different implementations do not only accept + * the same set of valid signatures, but also reject the same set of signatures. + * The only means to accomplish that is by strictly obeying a standard, and not + * accepting anything else. + * + * Nonetheless, sometimes there is a need for compatibility with systems that + * use signatures which do not strictly obey DER. The snippet below shows how + * certain violations are easily supported. You may need to adapt it. + * + * Do not use this for new systems. Use well-defined DER or compact signatures + * instead if you have the choice (see secp256k1_ecdsa_signature_parse_der and + * secp256k1_ecdsa_signature_parse_compact). + * + * The supported violations are: + * - All numbers are parsed as nonnegative integers, even though X.609-0207 + * section 8.3.3 specifies that integers are always encoded as two's + * complement. + * - Integers can have length 0, even though section 8.3.1 says they can't. + * - Integers with overly long padding are accepted, violation section + * 8.3.2. + * - 127-byte long length descriptors are accepted, even though section + * 8.1.3.5.c says that they are not. + * - Trailing garbage data inside or after the signature is ignored. + * - The length descriptor of the sequence is ignored. + * + * Compared to for example OpenSSL, many violations are NOT supported: + * - Using overly long tag descriptors for the sequence or integers inside, + * violating section 8.1.2.2. + * - Encoding primitive integers as constructed values, violating section + * 8.3.1. + */ + +#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ +#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ + +#include + +# ifdef __cplusplus +extern "C" { +# endif + +/** Parse a signature in "lax DER" format + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input: a pointer to the signature to be parsed + * inputlen: the length of the array pointed to be input + * + * This function will accept any valid DER encoded signature, even if the + * encoded numbers are out of range. In addition, it will accept signatures + * which violate the DER spec in various ways. Its purpose is to allow + * validation of the Bitcoin blockchain, which includes non-DER signatures + * from before the network rules were updated to enforce DER. Note that + * the set of supported violations is a strict subset of what OpenSSL will + * accept. + * + * After the call, sig will always be initialized. If parsing failed or the + * encoded numbers are out of range, signature validation with it is + * guaranteed to fail for every message and public key. + */ +int ecdsa_signature_parse_der_lax( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature* sig, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c new file mode 100644 index 00000000..c2e63b4b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.c @@ -0,0 +1,113 @@ +/********************************************************************** + * Copyright (c) 2014, 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include + +#include "lax_der_privatekey_parsing.h" + +int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *out32, const unsigned char *privkey, size_t privkeylen) { + const unsigned char *end = privkey + privkeylen; + int lenb = 0; + int len = 0; + memset(out32, 0, 32); + /* sequence header */ + if (end < privkey+1 || *privkey != 0x30) { + return 0; + } + privkey++; + /* sequence length constructor */ + if (end < privkey+1 || !(*privkey & 0x80)) { + return 0; + } + lenb = *privkey & ~0x80; privkey++; + if (lenb < 1 || lenb > 2) { + return 0; + } + if (end < privkey+lenb) { + return 0; + } + /* sequence length */ + len = privkey[lenb-1] | (lenb > 1 ? privkey[lenb-2] << 8 : 0); + privkey += lenb; + if (end < privkey+len) { + return 0; + } + /* sequence element 0: version number (=1) */ + if (end < privkey+3 || privkey[0] != 0x02 || privkey[1] != 0x01 || privkey[2] != 0x01) { + return 0; + } + privkey += 3; + /* sequence element 1: octet string, up to 32 bytes */ + if (end < privkey+2 || privkey[0] != 0x04 || privkey[1] > 0x20 || end < privkey+2+privkey[1]) { + return 0; + } + memcpy(out32 + 32 - privkey[1], privkey + 2, privkey[1]); + if (!secp256k1_ec_seckey_verify(ctx, out32)) { + memset(out32, 0, 32); + return 0; + } + return 1; +} + +int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) { + secp256k1_pubkey pubkey; + size_t pubkeylen = 0; + if (!secp256k1_ec_pubkey_create(ctx, &pubkey, key32)) { + *privkeylen = 0; + return 0; + } + if (compressed) { + static const unsigned char begin[] = { + 0x30,0x81,0xD3,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0x85,0x30,0x81,0x82,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x21,0x02,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, + 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, + 0x17,0x98,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, + 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x24,0x03,0x22,0x00 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + memcpy(ptr, key32, 32); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + pubkeylen = 33; + secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED); + ptr += pubkeylen; + *privkeylen = ptr - privkey; + } else { + static const unsigned char begin[] = { + 0x30,0x82,0x01,0x13,0x02,0x01,0x01,0x04,0x20 + }; + static const unsigned char middle[] = { + 0xA0,0x81,0xA5,0x30,0x81,0xA2,0x02,0x01,0x01,0x30,0x2C,0x06,0x07,0x2A,0x86,0x48, + 0xCE,0x3D,0x01,0x01,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F,0x30,0x06,0x04,0x01,0x00,0x04,0x01,0x07,0x04, + 0x41,0x04,0x79,0xBE,0x66,0x7E,0xF9,0xDC,0xBB,0xAC,0x55,0xA0,0x62,0x95,0xCE,0x87, + 0x0B,0x07,0x02,0x9B,0xFC,0xDB,0x2D,0xCE,0x28,0xD9,0x59,0xF2,0x81,0x5B,0x16,0xF8, + 0x17,0x98,0x48,0x3A,0xDA,0x77,0x26,0xA3,0xC4,0x65,0x5D,0xA4,0xFB,0xFC,0x0E,0x11, + 0x08,0xA8,0xFD,0x17,0xB4,0x48,0xA6,0x85,0x54,0x19,0x9C,0x47,0xD0,0x8F,0xFB,0x10, + 0xD4,0xB8,0x02,0x21,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFE,0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B,0xBF,0xD2,0x5E, + 0x8C,0xD0,0x36,0x41,0x41,0x02,0x01,0x01,0xA1,0x44,0x03,0x42,0x00 + }; + unsigned char *ptr = privkey; + memcpy(ptr, begin, sizeof(begin)); ptr += sizeof(begin); + memcpy(ptr, key32, 32); ptr += 32; + memcpy(ptr, middle, sizeof(middle)); ptr += sizeof(middle); + pubkeylen = 65; + secp256k1_ec_pubkey_serialize(ctx, ptr, &pubkeylen, &pubkey, SECP256K1_EC_UNCOMPRESSED); + ptr += pubkeylen; + *privkeylen = ptr - privkey; + } + return 1; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h new file mode 100644 index 00000000..2fd088f8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/contrib/lax_der_privatekey_parsing.h @@ -0,0 +1,90 @@ +/********************************************************************** + * Copyright (c) 2014, 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +/**** + * Please do not link this file directly. It is not part of the libsecp256k1 + * project and does not promise any stability in its API, functionality or + * presence. Projects which use this code should instead copy this header + * and its accompanying .c file directly into their codebase. + ****/ + +/* This file contains code snippets that parse DER private keys with + * various errors and violations. This is not a part of the library + * itself, because the allowed violations are chosen arbitrarily and + * do not follow or establish any standard. + * + * It also contains code to serialize private keys in a compatible + * manner. + * + * These functions are meant for compatibility with applications + * that require BER encoded keys. When working with secp256k1-specific + * code, the simple 32-byte private keys normally used by the + * library are sufficient. + */ + +#ifndef _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ +#define _SECP256K1_CONTRIB_BER_PRIVATEKEY_H_ + +#include + +# ifdef __cplusplus +extern "C" { +# endif + +/** Export a private key in DER format. + * + * Returns: 1 if the private key was valid. + * Args: ctx: pointer to a context object, initialized for signing (cannot + * be NULL) + * Out: privkey: pointer to an array for storing the private key in BER. + * Should have space for 279 bytes, and cannot be NULL. + * privkeylen: Pointer to an int where the length of the private key in + * privkey will be stored. + * In: seckey: pointer to a 32-byte secret key to export. + * compressed: 1 if the key should be exported in + * compressed format, 0 otherwise + * + * This function is purely meant for compatibility with applications that + * require BER encoded keys. When working with secp256k1-specific code, the + * simple 32-byte private keys are sufficient. + * + * Note that this function does not guarantee correct DER output. It is + * guaranteed to be parsable by secp256k1_ec_privkey_import_der + */ +SECP256K1_WARN_UNUSED_RESULT int ec_privkey_export_der( + const secp256k1_context* ctx, + unsigned char *privkey, + size_t *privkeylen, + const unsigned char *seckey, + int compressed +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Import a private key in DER format. + * Returns: 1 if a private key was extracted. + * Args: ctx: pointer to a context object (cannot be NULL). + * Out: seckey: pointer to a 32-byte array for storing the private key. + * (cannot be NULL). + * In: privkey: pointer to a private key in DER format (cannot be NULL). + * privkeylen: length of the DER private key pointed to be privkey. + * + * This function will accept more than just strict DER, and even allow some BER + * violations. The public key stored inside the DER-encoded private key is not + * verified for correctness, nor are the curve parameters. Use this function + * only if you know in advance it is supposed to contain a secp256k1 private + * key. + */ +SECP256K1_WARN_UNUSED_RESULT int ec_privkey_import_der( + const secp256k1_context* ctx, + unsigned char *seckey, + const unsigned char *privkey, + size_t privkeylen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h new file mode 100644 index 00000000..f268e309 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1.h @@ -0,0 +1,577 @@ +#ifndef _SECP256K1_ +# define _SECP256K1_ + +# ifdef __cplusplus +extern "C" { +# endif + +#include + +/* These rules specify the order of arguments in API calls: + * + * 1. Context pointers go first, followed by output arguments, combined + * output/input arguments, and finally input-only arguments. + * 2. Array lengths always immediately the follow the argument whose length + * they describe, even if this violates rule 1. + * 3. Within the OUT/OUTIN/IN groups, pointers to data that is typically generated + * later go first. This means: signatures, public nonces, private nonces, + * messages, public keys, secret keys, tweaks. + * 4. Arguments that are not data pointers go last, from more complex to less + * complex: function pointers, algorithm names, messages, void pointers, + * counts, flags, booleans. + * 5. Opaque data pointers follow the function pointer they are to be passed to. + */ + +/** Opaque data structure that holds context information (precomputed tables etc.). + * + * The purpose of context structures is to cache large precomputed data tables + * that are expensive to construct, and also to maintain the randomization data + * for blinding. + * + * Do not create a new context object for each operation, as construction is + * far slower than all other API calls (~100 times slower than an ECDSA + * verification). + * + * A constructed context can safely be used from multiple threads + * simultaneously, but API call that take a non-const pointer to a context + * need exclusive access to it. In particular this is the case for + * secp256k1_context_destroy and secp256k1_context_randomize. + * + * Regarding randomization, either do it once at creation time (in which case + * you do not need any locking for the other calls), or use a read-write lock. + */ +typedef struct secp256k1_context_struct secp256k1_context; + +/** Opaque data structure that holds a parsed and valid public key. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use secp256k1_ec_pubkey_serialize and secp256k1_ec_pubkey_parse. + */ +typedef struct { + unsigned char data[64]; +} secp256k1_pubkey; + +/** Opaque data structured that holds a parsed ECDSA signature. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 64 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage, transmission, or + * comparison, use the secp256k1_ecdsa_signature_serialize_* and + * secp256k1_ecdsa_signature_serialize_* functions. + */ +typedef struct { + unsigned char data[64]; +} secp256k1_ecdsa_signature; + +/** A pointer to a function to deterministically generate a nonce. + * + * Returns: 1 if a nonce was successfully generated. 0 will cause signing to fail. + * Out: nonce32: pointer to a 32-byte array to be filled by the function. + * In: msg32: the 32-byte message hash being verified (will not be NULL) + * key32: pointer to a 32-byte secret key (will not be NULL) + * algo16: pointer to a 16-byte array describing the signature + * algorithm (will be NULL for ECDSA for compatibility). + * data: Arbitrary data pointer that is passed through. + * attempt: how many iterations we have tried to find a nonce. + * This will almost always be 0, but different attempt values + * are required to result in a different nonce. + * + * Except for test cases, this function should compute some cryptographic hash of + * the message, the algorithm, the key and the attempt. + */ +typedef int (*secp256k1_nonce_function)( + unsigned char *nonce32, + const unsigned char *msg32, + const unsigned char *key32, + const unsigned char *algo16, + void *data, + unsigned int attempt +); + +# if !defined(SECP256K1_GNUC_PREREQ) +# if defined(__GNUC__)&&defined(__GNUC_MINOR__) +# define SECP256K1_GNUC_PREREQ(_maj,_min) \ + ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) +# else +# define SECP256K1_GNUC_PREREQ(_maj,_min) 0 +# endif +# endif + +# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if SECP256K1_GNUC_PREREQ(2,7) +# define SECP256K1_INLINE __inline__ +# elif (defined(_MSC_VER)) +# define SECP256K1_INLINE __inline +# else +# define SECP256K1_INLINE +# endif +# else +# define SECP256K1_INLINE inline +# endif + +#ifndef SECP256K1_API +# if defined(_WIN32) +# ifdef SECP256K1_BUILD +# define SECP256K1_API __declspec(dllexport) +# else +# define SECP256K1_API +# endif +# elif defined(__GNUC__) && defined(SECP256K1_BUILD) +# define SECP256K1_API __attribute__ ((visibility ("default"))) +# else +# define SECP256K1_API +# endif +#endif + +/**Warning attributes + * NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out + * some paranoid null checks. */ +# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__)) +# else +# define SECP256K1_WARN_UNUSED_RESULT +# endif +# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4) +# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x))) +# else +# define SECP256K1_ARG_NONNULL(_x) +# endif + +/** All flags' lower 8 bits indicate what they're for. Do not use directly. */ +#define SECP256K1_FLAGS_TYPE_MASK ((1 << 8) - 1) +#define SECP256K1_FLAGS_TYPE_CONTEXT (1 << 0) +#define SECP256K1_FLAGS_TYPE_COMPRESSION (1 << 1) +/** The higher bits contain the actual data. Do not use directly. */ +#define SECP256K1_FLAGS_BIT_CONTEXT_VERIFY (1 << 8) +#define SECP256K1_FLAGS_BIT_CONTEXT_SIGN (1 << 9) +#define SECP256K1_FLAGS_BIT_COMPRESSION (1 << 8) + +/** Flags to pass to secp256k1_context_create. */ +#define SECP256K1_CONTEXT_VERIFY (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) +#define SECP256K1_CONTEXT_SIGN (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) +#define SECP256K1_CONTEXT_NONE (SECP256K1_FLAGS_TYPE_CONTEXT) + +/** Flag to pass to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export. */ +#define SECP256K1_EC_COMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) +#define SECP256K1_EC_UNCOMPRESSED (SECP256K1_FLAGS_TYPE_COMPRESSION) + +/** Create a secp256k1 context object. + * + * Returns: a newly created context object. + * In: flags: which parts of the context to initialize. + */ +SECP256K1_API secp256k1_context* secp256k1_context_create( + unsigned int flags +) SECP256K1_WARN_UNUSED_RESULT; + +/** Copies a secp256k1 context object. + * + * Returns: a newly created context object. + * Args: ctx: an existing context to copy (cannot be NULL) + */ +SECP256K1_API secp256k1_context* secp256k1_context_clone( + const secp256k1_context* ctx +) SECP256K1_ARG_NONNULL(1) SECP256K1_WARN_UNUSED_RESULT; + +/** Destroy a secp256k1 context object. + * + * The context pointer may not be used afterwards. + * Args: ctx: an existing context to destroy (cannot be NULL) + */ +SECP256K1_API void secp256k1_context_destroy( + secp256k1_context* ctx +); + +/** Set a callback function to be called when an illegal argument is passed to + * an API call. It will only trigger for violations that are mentioned + * explicitly in the header. + * + * The philosophy is that these shouldn't be dealt with through a + * specific return value, as calling code should not have branches to deal with + * the case that this code itself is broken. + * + * On the other hand, during debug stage, one would want to be informed about + * such mistakes, and the default (crashing) may be inadvisable. + * When this callback is triggered, the API function called is guaranteed not + * to cause a crash, though its return value and output arguments are + * undefined. + * + * Args: ctx: an existing context object (cannot be NULL) + * In: fun: a pointer to a function to call when an illegal argument is + * passed to the API, taking a message and an opaque pointer + * (NULL restores a default handler that calls abort). + * data: the opaque pointer to pass to fun above. + */ +SECP256K1_API void secp256k1_context_set_illegal_callback( + secp256k1_context* ctx, + void (*fun)(const char* message, void* data), + const void* data +) SECP256K1_ARG_NONNULL(1); + +/** Set a callback function to be called when an internal consistency check + * fails. The default is crashing. + * + * This can only trigger in case of a hardware failure, miscompilation, + * memory corruption, serious bug in the library, or other error would can + * otherwise result in undefined behaviour. It will not trigger due to mere + * incorrect usage of the API (see secp256k1_context_set_illegal_callback + * for that). After this callback returns, anything may happen, including + * crashing. + * + * Args: ctx: an existing context object (cannot be NULL) + * In: fun: a pointer to a function to call when an internal error occurs, + * taking a message and an opaque pointer (NULL restores a default + * handler that calls abort). + * data: the opaque pointer to pass to fun above. + */ +SECP256K1_API void secp256k1_context_set_error_callback( + secp256k1_context* ctx, + void (*fun)(const char* message, void* data), + const void* data +) SECP256K1_ARG_NONNULL(1); + +/** Parse a variable-length public key into the pubkey object. + * + * Returns: 1 if the public key was fully valid. + * 0 if the public key could not be parsed or is invalid. + * Args: ctx: a secp256k1 context object. + * Out: pubkey: pointer to a pubkey object. If 1 is returned, it is set to a + * parsed version of input. If not, its value is undefined. + * In: input: pointer to a serialized public key + * inputlen: length of the array pointed to by input + * + * This function supports parsing compressed (33 bytes, header byte 0x02 or + * 0x03), uncompressed (65 bytes, header byte 0x04), or hybrid (65 bytes, header + * byte 0x06 or 0x07) format public keys. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_parse( + const secp256k1_context* ctx, + secp256k1_pubkey* pubkey, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize a pubkey object into a serialized byte sequence. + * + * Returns: 1 always. + * Args: ctx: a secp256k1 context object. + * Out: output: a pointer to a 65-byte (if compressed==0) or 33-byte (if + * compressed==1) byte array to place the serialized key + * in. + * In/Out: outputlen: a pointer to an integer which is initially set to the + * size of output, and is overwritten with the written + * size. + * In: pubkey: a pointer to a secp256k1_pubkey containing an + * initialized public key. + * flags: SECP256K1_EC_COMPRESSED if serialization should be in + * compressed format, otherwise SECP256K1_EC_UNCOMPRESSED. + */ +SECP256K1_API int secp256k1_ec_pubkey_serialize( + const secp256k1_context* ctx, + unsigned char *output, + size_t *outputlen, + const secp256k1_pubkey* pubkey, + unsigned int flags +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Parse an ECDSA signature in compact (64 bytes) format. + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input64: a pointer to the 64-byte array to parse + * + * The signature must consist of a 32-byte big endian R value, followed by a + * 32-byte big endian S value. If R or S fall outside of [0..order-1], the + * encoding is invalid. R and S with value 0 are allowed in the encoding. + * + * After the call, sig will always be initialized. If parsing failed or R or + * S are zero, the resulting sig value is guaranteed to fail validation for any + * message and public key. + */ +SECP256K1_API int secp256k1_ecdsa_signature_parse_compact( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature* sig, + const unsigned char *input64 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Parse a DER ECDSA signature. + * + * Returns: 1 when the signature could be parsed, 0 otherwise. + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input: a pointer to the signature to be parsed + * inputlen: the length of the array pointed to be input + * + * This function will accept any valid DER encoded signature, even if the + * encoded numbers are out of range. + * + * After the call, sig will always be initialized. If parsing failed or the + * encoded numbers are out of range, signature validation with it is + * guaranteed to fail for every message and public key. + */ +SECP256K1_API int secp256k1_ecdsa_signature_parse_der( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature* sig, + const unsigned char *input, + size_t inputlen +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an ECDSA signature in DER format. + * + * Returns: 1 if enough space was available to serialize, 0 otherwise + * Args: ctx: a secp256k1 context object + * Out: output: a pointer to an array to store the DER serialization + * In/Out: outputlen: a pointer to a length integer. Initially, this integer + * should be set to the length of output. After the call + * it will be set to the length of the serialization (even + * if 0 was returned). + * In: sig: a pointer to an initialized signature object + */ +SECP256K1_API int secp256k1_ecdsa_signature_serialize_der( + const secp256k1_context* ctx, + unsigned char *output, + size_t *outputlen, + const secp256k1_ecdsa_signature* sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Serialize an ECDSA signature in compact (64 byte) format. + * + * Returns: 1 + * Args: ctx: a secp256k1 context object + * Out: output64: a pointer to a 64-byte array to store the compact serialization + * In: sig: a pointer to an initialized signature object + * + * See secp256k1_ecdsa_signature_parse_compact for details about the encoding. + */ +SECP256K1_API int secp256k1_ecdsa_signature_serialize_compact( + const secp256k1_context* ctx, + unsigned char *output64, + const secp256k1_ecdsa_signature* sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Verify an ECDSA signature. + * + * Returns: 1: correct signature + * 0: incorrect or unparseable signature + * Args: ctx: a secp256k1 context object, initialized for verification. + * In: sig: the signature being verified (cannot be NULL) + * msg32: the 32-byte message hash being verified (cannot be NULL) + * pubkey: pointer to an initialized public key to verify with (cannot be NULL) + * + * To avoid accepting malleable signatures, only ECDSA signatures in lower-S + * form are accepted. + * + * If you need to accept ECDSA signatures from sources that do not obey this + * rule, apply secp256k1_ecdsa_signature_normalize to the signature prior to + * validation, but be aware that doing so results in malleable signatures. + * + * For details, see the comments for that function. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_verify( + const secp256k1_context* ctx, + const secp256k1_ecdsa_signature *sig, + const unsigned char *msg32, + const secp256k1_pubkey *pubkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Convert a signature to a normalized lower-S form. + * + * Returns: 1 if sigin was not normalized, 0 if it already was. + * Args: ctx: a secp256k1 context object + * Out: sigout: a pointer to a signature to fill with the normalized form, + * or copy if the input was already normalized. (can be NULL if + * you're only interested in whether the input was already + * normalized). + * In: sigin: a pointer to a signature to check/normalize (cannot be NULL, + * can be identical to sigout) + * + * With ECDSA a third-party can forge a second distinct signature of the same + * message, given a single initial signature, but without knowing the key. This + * is done by negating the S value modulo the order of the curve, 'flipping' + * the sign of the random point R which is not included in the signature. + * + * Forgery of the same message isn't universally problematic, but in systems + * where message malleability or uniqueness of signatures is important this can + * cause issues. This forgery can be blocked by all verifiers forcing signers + * to use a normalized form. + * + * The lower-S form reduces the size of signatures slightly on average when + * variable length encodings (such as DER) are used and is cheap to verify, + * making it a good choice. Security of always using lower-S is assured because + * anyone can trivially modify a signature after the fact to enforce this + * property anyway. + * + * The lower S value is always between 0x1 and + * 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, + * inclusive. + * + * No other forms of ECDSA malleability are known and none seem likely, but + * there is no formal proof that ECDSA, even with this additional restriction, + * is free of other malleability. Commonly used serialization schemes will also + * accept various non-unique encodings, so care should be taken when this + * property is required for an application. + * + * The secp256k1_ecdsa_sign function will by default create signatures in the + * lower-S form, and secp256k1_ecdsa_verify will not accept others. In case + * signatures come from a system that cannot enforce this property, + * secp256k1_ecdsa_signature_normalize must be called before verification. + */ +SECP256K1_API int secp256k1_ecdsa_signature_normalize( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature *sigout, + const secp256k1_ecdsa_signature *sigin +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(3); + +/** An implementation of RFC6979 (using HMAC-SHA256) as nonce generation function. + * If a data pointer is passed, it is assumed to be a pointer to 32 bytes of + * extra entropy. + */ +SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_rfc6979; + +/** A default safe nonce generation function (currently equal to secp256k1_nonce_function_rfc6979). */ +SECP256K1_API extern const secp256k1_nonce_function secp256k1_nonce_function_default; + +/** Create an ECDSA signature. + * + * Returns: 1: signature created + * 0: the nonce generation function failed, or the private key was invalid. + * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) + * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) + * In: msg32: the 32-byte message hash being signed (cannot be NULL) + * seckey: pointer to a 32-byte secret key (cannot be NULL) + * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used + * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) + * + * The created signature is always in lower-S form. See + * secp256k1_ecdsa_signature_normalize for more details. + */ +SECP256K1_API int secp256k1_ecdsa_sign( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature *sig, + const unsigned char *msg32, + const unsigned char *seckey, + secp256k1_nonce_function noncefp, + const void *ndata +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Verify an ECDSA secret key. + * + * Returns: 1: secret key is valid + * 0: secret key is invalid + * Args: ctx: pointer to a context object (cannot be NULL) + * In: seckey: pointer to a 32-byte secret key (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_seckey_verify( + const secp256k1_context* ctx, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2); + +/** Compute the public key for a secret key. + * + * Returns: 1: secret was valid, public key stores + * 0: secret was invalid, try again + * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) + * Out: pubkey: pointer to the created public key (cannot be NULL) + * In: seckey: pointer to a 32-byte private key (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_create( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey, + const unsigned char *seckey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a private key by adding tweak to it. + * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for + * uniformly random 32-byte arrays, or if the resulting private key + * would be invalid (only when the tweak is the complement of the + * private key). 1 otherwise. + * Args: ctx: pointer to a context object (cannot be NULL). + * In/Out: seckey: pointer to a 32-byte private key. + * In: tweak: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_add( + const secp256k1_context* ctx, + unsigned char *seckey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a public key by adding tweak times the generator to it. + * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for + * uniformly random 32-byte arrays, or if the resulting public key + * would be invalid (only when the tweak is the complement of the + * corresponding private key). 1 otherwise. + * Args: ctx: pointer to a context object initialized for validation + * (cannot be NULL). + * In/Out: pubkey: pointer to a public key object. + * In: tweak: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_add( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a private key by multiplying it by a tweak. + * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for + * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. + * Args: ctx: pointer to a context object (cannot be NULL). + * In/Out: seckey: pointer to a 32-byte private key. + * In: tweak: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_privkey_tweak_mul( + const secp256k1_context* ctx, + unsigned char *seckey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Tweak a public key by multiplying it by a tweak value. + * Returns: 0 if the tweak was out of range (chance of around 1 in 2^128 for + * uniformly random 32-byte arrays, or equal to zero. 1 otherwise. + * Args: ctx: pointer to a context object initialized for validation + * (cannot be NULL). + * In/Out: pubkey: pointer to a public key obkect. + * In: tweak: pointer to a 32-byte tweak. + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_tweak_mul( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey, + const unsigned char *tweak +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Updates the context randomization. + * Returns: 1: randomization successfully updated + * 0: error + * Args: ctx: pointer to a context object (cannot be NULL) + * In: seed32: pointer to a 32-byte random seed (NULL resets to initial state) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_context_randomize( + secp256k1_context* ctx, + const unsigned char *seed32 +) SECP256K1_ARG_NONNULL(1); + +/** Add a number of public keys together. + * Returns: 1: the sum of the public keys is valid. + * 0: the sum of the public keys is not valid. + * Args: ctx: pointer to a context object + * Out: out: pointer to a public key object for placing the resulting public key + * (cannot be NULL) + * In: ins: pointer to array of pointers to public keys (cannot be NULL) + * n: the number of public keys to add together (must be at least 1) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ec_pubkey_combine( + const secp256k1_context* ctx, + secp256k1_pubkey *out, + const secp256k1_pubkey * const * ins, + size_t n +) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h new file mode 100644 index 00000000..4b84d7a9 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_ecdh.h @@ -0,0 +1,31 @@ +#ifndef _SECP256K1_ECDH_ +# define _SECP256K1_ECDH_ + +# include "secp256k1.h" + +# ifdef __cplusplus +extern "C" { +# endif + +/** Compute an EC Diffie-Hellman secret in constant time + * Returns: 1: exponentiation was successful + * 0: scalar was invalid (zero or overflow) + * Args: ctx: pointer to a context object (cannot be NULL) + * Out: result: a 32-byte array which will be populated by an ECDH + * secret computed from the point and scalar + * In: pubkey: a pointer to a secp256k1_pubkey containing an + * initialized public key + * privkey: a 32-byte scalar with which to multiply the point + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdh( + const secp256k1_context* ctx, + unsigned char *result, + const secp256k1_pubkey *pubkey, + const unsigned char *privkey +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h new file mode 100644 index 00000000..05537972 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include/secp256k1_recovery.h @@ -0,0 +1,110 @@ +#ifndef _SECP256K1_RECOVERY_ +# define _SECP256K1_RECOVERY_ + +# include "secp256k1.h" + +# ifdef __cplusplus +extern "C" { +# endif + +/** Opaque data structured that holds a parsed ECDSA signature, + * supporting pubkey recovery. + * + * The exact representation of data inside is implementation defined and not + * guaranteed to be portable between different platforms or versions. It is + * however guaranteed to be 65 bytes in size, and can be safely copied/moved. + * If you need to convert to a format suitable for storage or transmission, use + * the secp256k1_ecdsa_signature_serialize_* and + * secp256k1_ecdsa_signature_parse_* functions. + * + * Furthermore, it is guaranteed that identical signatures (including their + * recoverability) will have identical representation, so they can be + * memcmp'ed. + */ +typedef struct { + unsigned char data[65]; +} secp256k1_ecdsa_recoverable_signature; + +/** Parse a compact ECDSA signature (64 bytes + recovery id). + * + * Returns: 1 when the signature could be parsed, 0 otherwise + * Args: ctx: a secp256k1 context object + * Out: sig: a pointer to a signature object + * In: input64: a pointer to a 64-byte compact signature + * recid: the recovery id (0, 1, 2 or 3) + */ +SECP256K1_API int secp256k1_ecdsa_recoverable_signature_parse_compact( + const secp256k1_context* ctx, + secp256k1_ecdsa_recoverable_signature* sig, + const unsigned char *input64, + int recid +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Convert a recoverable signature into a normal signature. + * + * Returns: 1 + * Out: sig: a pointer to a normal signature (cannot be NULL). + * In: sigin: a pointer to a recoverable signature (cannot be NULL). + */ +SECP256K1_API int secp256k1_ecdsa_recoverable_signature_convert( + const secp256k1_context* ctx, + secp256k1_ecdsa_signature* sig, + const secp256k1_ecdsa_recoverable_signature* sigin +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3); + +/** Serialize an ECDSA signature in compact format (64 bytes + recovery id). + * + * Returns: 1 + * Args: ctx: a secp256k1 context object + * Out: output64: a pointer to a 64-byte array of the compact signature (cannot be NULL) + * recid: a pointer to an integer to hold the recovery id (can be NULL). + * In: sig: a pointer to an initialized signature object (cannot be NULL) + */ +SECP256K1_API int secp256k1_ecdsa_recoverable_signature_serialize_compact( + const secp256k1_context* ctx, + unsigned char *output64, + int *recid, + const secp256k1_ecdsa_recoverable_signature* sig +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Create a recoverable ECDSA signature. + * + * Returns: 1: signature created + * 0: the nonce generation function failed, or the private key was invalid. + * Args: ctx: pointer to a context object, initialized for signing (cannot be NULL) + * Out: sig: pointer to an array where the signature will be placed (cannot be NULL) + * In: msg32: the 32-byte message hash being signed (cannot be NULL) + * seckey: pointer to a 32-byte secret key (cannot be NULL) + * noncefp:pointer to a nonce generation function. If NULL, secp256k1_nonce_function_default is used + * ndata: pointer to arbitrary data used by the nonce generation function (can be NULL) + */ +SECP256K1_API int secp256k1_ecdsa_sign_recoverable( + const secp256k1_context* ctx, + secp256k1_ecdsa_recoverable_signature *sig, + const unsigned char *msg32, + const unsigned char *seckey, + secp256k1_nonce_function noncefp, + const void *ndata +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +/** Recover an ECDSA public key from a signature. + * + * Returns: 1: public key successfully recovered (which guarantees a correct signature). + * 0: otherwise. + * Args: ctx: pointer to a context object, initialized for verification (cannot be NULL) + * Out: pubkey: pointer to the recovered public key (cannot be NULL) + * In: sig: pointer to initialized signature that supports pubkey recovery (cannot be NULL) + * msg32: the 32-byte message hash assumed to be signed (cannot be NULL) + */ +SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_ecdsa_recover( + const secp256k1_context* ctx, + secp256k1_pubkey *pubkey, + const secp256k1_ecdsa_recoverable_signature *sig, + const unsigned char *msg32 +) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4); + +# ifdef __cplusplus +} +# endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in new file mode 100644 index 00000000..a0d006f1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/libsecp256k1.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libsecp256k1 +Description: Optimized C library for EC operations on curve secp256k1 +URL: https://github.com/bitcoin-core/secp256k1 +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} +Libs.private: @SECP_LIBS@ +Libs: -L${libdir} -lsecp256k1 + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/obj/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage new file mode 100644 index 00000000..ab580c5b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/group_prover.sage @@ -0,0 +1,322 @@ +# This code supports verifying group implementations which have branches +# or conditional statements (like cmovs), by allowing each execution path +# to independently set assumptions on input or intermediary variables. +# +# The general approach is: +# * A constraint is a tuple of two sets of of symbolic expressions: +# the first of which are required to evaluate to zero, the second of which +# are required to evaluate to nonzero. +# - A constraint is said to be conflicting if any of its nonzero expressions +# is in the ideal with basis the zero expressions (in other words: when the +# zero expressions imply that one of the nonzero expressions are zero). +# * There is a list of laws that describe the intended behaviour, including +# laws for addition and doubling. Each law is called with the symbolic point +# coordinates as arguments, and returns: +# - A constraint describing the assumptions under which it is applicable, +# called "assumeLaw" +# - A constraint describing the requirements of the law, called "require" +# * Implementations are transliterated into functions that operate as well on +# algebraic input points, and are called once per combination of branches +# exectured. Each execution returns: +# - A constraint describing the assumptions this implementation requires +# (such as Z1=1), called "assumeFormula" +# - A constraint describing the assumptions this specific branch requires, +# but which is by construction guaranteed to cover the entire space by +# merging the results from all branches, called "assumeBranch" +# - The result of the computation +# * All combinations of laws with implementation branches are tried, and: +# - If the combination of assumeLaw, assumeFormula, and assumeBranch results +# in a conflict, it means this law does not apply to this branch, and it is +# skipped. +# - For others, we try to prove the require constraints hold, assuming the +# information in assumeLaw + assumeFormula + assumeBranch, and if this does +# not succeed, we fail. +# + To prove an expression is zero, we check whether it belongs to the +# ideal with the assumed zero expressions as basis. This test is exact. +# + To prove an expression is nonzero, we check whether each of its +# factors is contained in the set of nonzero assumptions' factors. +# This test is not exact, so various combinations of original and +# reduced expressions' factors are tried. +# - If we succeed, we print out the assumptions from assumeFormula that +# weren't implied by assumeLaw already. Those from assumeBranch are skipped, +# as we assume that all constraints in it are complementary with each other. +# +# Based on the sage verification scripts used in the Explicit-Formulas Database +# by Tanja Lange and others, see http://hyperelliptic.org/EFD + +class fastfrac: + """Fractions over rings.""" + + def __init__(self,R,top,bot=1): + """Construct a fractional, given a ring, a numerator, and denominator.""" + self.R = R + if parent(top) == ZZ or parent(top) == R: + self.top = R(top) + self.bot = R(bot) + elif top.__class__ == fastfrac: + self.top = top.top + self.bot = top.bot * bot + else: + self.top = R(numerator(top)) + self.bot = R(denominator(top)) * bot + + def iszero(self,I): + """Return whether this fraction is zero given an ideal.""" + return self.top in I and self.bot not in I + + def reduce(self,assumeZero): + zero = self.R.ideal(map(numerator, assumeZero)) + return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot)) + + def __add__(self,other): + """Add two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top + self.bot * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot + self.bot * other.top,self.bot * other.bot) + return NotImplemented + + def __sub__(self,other): + """Subtract two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top - self.bot * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot - self.bot * other.top,self.bot * other.bot) + return NotImplemented + + def __neg__(self): + """Return the negation of a fraction.""" + return fastfrac(self.R,-self.top,self.bot) + + def __mul__(self,other): + """Multiply two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top * other,self.bot) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.top,self.bot * other.bot) + return NotImplemented + + def __rmul__(self,other): + """Multiply something else with a fraction.""" + return self.__mul__(other) + + def __div__(self,other): + """Divide two fractions.""" + if parent(other) == ZZ: + return fastfrac(self.R,self.top,self.bot * other) + if other.__class__ == fastfrac: + return fastfrac(self.R,self.top * other.bot,self.bot * other.top) + return NotImplemented + + def __pow__(self,other): + """Compute a power of a fraction.""" + if parent(other) == ZZ: + if other < 0: + # Negative powers require flipping top and bottom + return fastfrac(self.R,self.bot ^ (-other),self.top ^ (-other)) + else: + return fastfrac(self.R,self.top ^ other,self.bot ^ other) + return NotImplemented + + def __str__(self): + return "fastfrac((" + str(self.top) + ") / (" + str(self.bot) + "))" + def __repr__(self): + return "%s" % self + + def numerator(self): + return self.top + +class constraints: + """A set of constraints, consisting of zero and nonzero expressions. + + Constraints can either be used to express knowledge or a requirement. + + Both the fields zero and nonzero are maps from expressions to description + strings. The expressions that are the keys in zero are required to be zero, + and the expressions that are the keys in nonzero are required to be nonzero. + + Note that (a != 0) and (b != 0) is the same as (a*b != 0), so all keys in + nonzero could be multiplied into a single key. This is often much less + efficient to work with though, so we keep them separate inside the + constraints. This allows higher-level code to do fast checks on the individual + nonzero elements, or combine them if needed for stronger checks. + + We can't multiply the different zero elements, as it would suffice for one of + the factors to be zero, instead of all of them. Instead, the zero elements are + typically combined into an ideal first. + """ + + def __init__(self, **kwargs): + if 'zero' in kwargs: + self.zero = dict(kwargs['zero']) + else: + self.zero = dict() + if 'nonzero' in kwargs: + self.nonzero = dict(kwargs['nonzero']) + else: + self.nonzero = dict() + + def negate(self): + return constraints(zero=self.nonzero, nonzero=self.zero) + + def __add__(self, other): + zero = self.zero.copy() + zero.update(other.zero) + nonzero = self.nonzero.copy() + nonzero.update(other.nonzero) + return constraints(zero=zero, nonzero=nonzero) + + def __str__(self): + return "constraints(zero=%s,nonzero=%s)" % (self.zero, self.nonzero) + + def __repr__(self): + return "%s" % self + + +def conflicts(R, con): + """Check whether any of the passed non-zero assumptions is implied by the zero assumptions""" + zero = R.ideal(map(numerator, con.zero)) + if 1 in zero: + return True + # First a cheap check whether any of the individual nonzero terms conflict on + # their own. + for nonzero in con.nonzero: + if nonzero.iszero(zero): + return True + # It can be the case that entries in the nonzero set do not individually + # conflict with the zero set, but their combination does. For example, knowing + # that either x or y is zero is equivalent to having x*y in the zero set. + # Having x or y individually in the nonzero set is not a conflict, but both + # simultaneously is, so that is the right thing to check for. + if reduce(lambda a,b: a * b, con.nonzero, fastfrac(R, 1)).iszero(zero): + return True + return False + + +def get_nonzero_set(R, assume): + """Calculate a simple set of nonzero expressions""" + zero = R.ideal(map(numerator, assume.zero)) + nonzero = set() + for nz in map(numerator, assume.nonzero): + for (f,n) in nz.factor(): + nonzero.add(f) + rnz = zero.reduce(nz) + for (f,n) in rnz.factor(): + nonzero.add(f) + return nonzero + + +def prove_nonzero(R, exprs, assume): + """Check whether an expression is provably nonzero, given assumptions""" + zero = R.ideal(map(numerator, assume.zero)) + nonzero = get_nonzero_set(R, assume) + expl = set() + ok = True + for expr in exprs: + if numerator(expr) in zero: + return (False, [exprs[expr]]) + allexprs = reduce(lambda a,b: numerator(a)*numerator(b), exprs, 1) + for (f, n) in allexprs.factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for (f, n) in zero.reduce(numerator(allexprs)).factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for expr in exprs: + for (f,n) in numerator(expr).factor(): + if f not in nonzero: + ok = False + if ok: + return (True, None) + ok = True + for expr in exprs: + for (f,n) in zero.reduce(numerator(expr)).factor(): + if f not in nonzero: + expl.add(exprs[expr]) + if expl: + return (False, list(expl)) + else: + return (True, None) + + +def prove_zero(R, exprs, assume): + """Check whether all of the passed expressions are provably zero, given assumptions""" + r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume) + if not r: + return (False, map(lambda x: "Possibly zero denominator: %s" % x, e)) + zero = R.ideal(map(numerator, assume.zero)) + nonzero = prod(x for x in assume.nonzero) + expl = [] + for expr in exprs: + if not expr.iszero(zero): + expl.append(exprs[expr]) + if not expl: + return (True, None) + return (False, expl) + + +def describe_extra(R, assume, assumeExtra): + """Describe what assumptions are added, given existing assumptions""" + zerox = assume.zero.copy() + zerox.update(assumeExtra.zero) + zero = R.ideal(map(numerator, assume.zero)) + zeroextra = R.ideal(map(numerator, zerox)) + nonzero = get_nonzero_set(R, assume) + ret = set() + # Iterate over the extra zero expressions + for base in assumeExtra.zero: + if base not in zero: + add = [] + for (f, n) in numerator(base).factor(): + if f not in nonzero: + add += ["%s" % f] + if add: + ret.add((" * ".join(add)) + " = 0 [%s]" % assumeExtra.zero[base]) + # Iterate over the extra nonzero expressions + for nz in assumeExtra.nonzero: + nzr = zeroextra.reduce(numerator(nz)) + if nzr not in zeroextra: + for (f,n) in nzr.factor(): + if zeroextra.reduce(f) not in nonzero: + ret.add("%s != 0" % zeroextra.reduce(f)) + return ", ".join(x for x in ret) + + +def check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require): + """Check a set of zero and nonzero requirements, given a set of zero and nonzero assumptions""" + assume = assumeLaw + assumeAssert + assumeBranch + + if conflicts(R, assume): + # This formula does not apply + return None + + describe = describe_extra(R, assumeLaw + assumeBranch, assumeAssert) + + ok, msg = prove_zero(R, require.zero, assume) + if not ok: + return "FAIL, %s fails (assuming %s)" % (str(msg), describe) + + res, expl = prove_nonzero(R, require.nonzero, assume) + if not res: + return "FAIL, %s fails (assuming %s)" % (str(expl), describe) + + if describe != "": + return "OK (assuming %s)" % describe + else: + return "OK" + + +def concrete_verify(c): + for k in c.zero: + if k != 0: + return (False, c.zero[k]) + for k in c.nonzero: + if k == 0: + return (False, c.nonzero[k]) + return (True, None) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage new file mode 100644 index 00000000..a97e732f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/secp256k1.sage @@ -0,0 +1,306 @@ +# Test libsecp256k1' group operation implementations using prover.sage + +import sys + +load("group_prover.sage") +load("weierstrass_prover.sage") + +def formula_secp256k1_gej_double_var(a): + """libsecp256k1's secp256k1_gej_double_var, used by various addition functions""" + rz = a.Z * a.Y + rz = rz * 2 + t1 = a.X^2 + t1 = t1 * 3 + t2 = t1^2 + t3 = a.Y^2 + t3 = t3 * 2 + t4 = t3^2 + t4 = t4 * 2 + t3 = t3 * a.X + rx = t3 + rx = rx * 4 + rx = -rx + rx = rx + t2 + t2 = -t2 + t3 = t3 * 6 + t3 = t3 + t2 + ry = t1 * t3 + t2 = -t4 + ry = ry + t2 + return jacobianpoint(rx, ry, rz) + +def formula_secp256k1_gej_add_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_var""" + if branch == 0: + return (constraints(), constraints(nonzero={a.Infinity : 'a_infinite'}), b) + if branch == 1: + return (constraints(), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) + z22 = b.Z^2 + z12 = a.Z^2 + u1 = a.X * z22 + u2 = b.X * z12 + s1 = a.Y * z22 + s1 = s1 * b.Z + s2 = b.Y * z12 + s2 = s2 * a.Z + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if branch == 2: + r = formula_secp256k1_gej_double_var(a) + return (constraints(), constraints(zero={h : 'h=0', i : 'i=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}), r) + if branch == 3: + return (constraints(), constraints(zero={h : 'h=0', a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h2 * h + h = h * b.Z + rz = a.Z * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_ge_var, which assume bz==1""" + if branch == 0: + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(nonzero={a.Infinity : 'a_infinite'}), b) + if branch == 1: + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite'}, nonzero={b.Infinity : 'b_infinite'}), a) + z12 = a.Z^2 + u1 = a.X + u2 = b.X * z12 + s1 = a.Y + s2 = b.Y * z12 + s2 = s2 * a.Z + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if (branch == 2): + r = formula_secp256k1_gej_double_var(a) + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) + if (branch == 3): + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h * h2 + rz = a.Z * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(zero={b.Z - 1 : 'b.z=1'}), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_zinv_var(branch, a, b): + """libsecp256k1's secp256k1_gej_add_zinv_var""" + bzinv = b.Z^(-1) + if branch == 0: + return (constraints(), constraints(nonzero={b.Infinity : 'b_infinite'}), a) + if branch == 1: + bzinv2 = bzinv^2 + bzinv3 = bzinv2 * bzinv + rx = b.X * bzinv2 + ry = b.Y * bzinv3 + rz = 1 + return (constraints(), constraints(zero={b.Infinity : 'b_finite'}, nonzero={a.Infinity : 'a_infinite'}), jacobianpoint(rx, ry, rz)) + azz = a.Z * bzinv + z12 = azz^2 + u1 = a.X + u2 = b.X * z12 + s1 = a.Y + s2 = b.Y * z12 + s2 = s2 * azz + h = -u1 + h = h + u2 + i = -s1 + i = i + s2 + if branch == 2: + r = formula_secp256k1_gej_double_var(a) + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0', i : 'i=0'}), r) + if branch == 3: + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite', h : 'h=0'}, nonzero={i : 'i!=0'}), point_at_infinity()) + i2 = i^2 + h2 = h^2 + h3 = h * h2 + rz = a.Z + rz = rz * h + t = u1 * h2 + rx = t + rx = rx * 2 + rx = rx + h3 + rx = -rx + rx = rx + i2 + ry = -rx + ry = ry + t + ry = ry * i + h3 = h3 * s1 + h3 = -h3 + ry = ry + h3 + return (constraints(), constraints(zero={a.Infinity : 'a_finite', b.Infinity : 'b_finite'}, nonzero={h : 'h!=0'}), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge(branch, a, b): + """libsecp256k1's secp256k1_gej_add_ge""" + zeroes = {} + nonzeroes = {} + a_infinity = False + if (branch & 4) != 0: + nonzeroes.update({a.Infinity : 'a_infinite'}) + a_infinity = True + else: + zeroes.update({a.Infinity : 'a_finite'}) + zz = a.Z^2 + u1 = a.X + u2 = b.X * zz + s1 = a.Y + s2 = b.Y * zz + s2 = s2 * a.Z + t = u1 + t = t + u2 + m = s1 + m = m + s2 + rr = t^2 + m_alt = -u2 + tt = u1 * m_alt + rr = rr + tt + degenerate = (branch & 3) == 3 + if (branch & 1) != 0: + zeroes.update({m : 'm_zero'}) + else: + nonzeroes.update({m : 'm_nonzero'}) + if (branch & 2) != 0: + zeroes.update({rr : 'rr_zero'}) + else: + nonzeroes.update({rr : 'rr_nonzero'}) + rr_alt = s1 + rr_alt = rr_alt * 2 + m_alt = m_alt + u1 + if not degenerate: + rr_alt = rr + m_alt = m + n = m_alt^2 + q = n * t + n = n^2 + if degenerate: + n = m + t = rr_alt^2 + rz = a.Z * m_alt + infinity = False + if (branch & 8) != 0: + if not a_infinity: + infinity = True + zeroes.update({rz : 'r.z=0'}) + else: + nonzeroes.update({rz : 'r.z!=0'}) + rz = rz * 2 + q = -q + t = t + q + rx = t + t = t * 2 + t = t + q + t = t * rr_alt + t = t + n + ry = -t + rx = rx * 4 + ry = ry * 4 + if a_infinity: + rx = b.X + ry = b.Y + rz = 1 + if infinity: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), point_at_infinity()) + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zeroes, nonzero=nonzeroes), jacobianpoint(rx, ry, rz)) + +def formula_secp256k1_gej_add_ge_old(branch, a, b): + """libsecp256k1's old secp256k1_gej_add_ge, which fails when ay+by=0 but ax!=bx""" + a_infinity = (branch & 1) != 0 + zero = {} + nonzero = {} + if a_infinity: + nonzero.update({a.Infinity : 'a_infinite'}) + else: + zero.update({a.Infinity : 'a_finite'}) + zz = a.Z^2 + u1 = a.X + u2 = b.X * zz + s1 = a.Y + s2 = b.Y * zz + s2 = s2 * a.Z + z = a.Z + t = u1 + t = t + u2 + m = s1 + m = m + s2 + n = m^2 + q = n * t + n = n^2 + rr = t^2 + t = u1 * u2 + t = -t + rr = rr + t + t = rr^2 + rz = m * z + infinity = False + if (branch & 2) != 0: + if not a_infinity: + infinity = True + else: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(nonzero={z : 'conflict_a'}, zero={z : 'conflict_b'}), point_at_infinity()) + zero.update({rz : 'r.z=0'}) + else: + nonzero.update({rz : 'r.z!=0'}) + rz = rz * (0 if a_infinity else 2) + rx = t + q = -q + rx = rx + q + q = q * 3 + t = t * 2 + t = t + q + t = t * rr + t = t + n + ry = -t + rx = rx * (0 if a_infinity else 4) + ry = ry * (0 if a_infinity else 4) + t = b.X + t = t * (1 if a_infinity else 0) + rx = rx + t + t = b.Y + t = t * (1 if a_infinity else 0) + ry = ry + t + t = (1 if a_infinity else 0) + rz = rz + t + if infinity: + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), point_at_infinity()) + return (constraints(zero={b.Z - 1 : 'b.z=1', b.Infinity : 'b_finite'}), constraints(zero=zero, nonzero=nonzero), jacobianpoint(rx, ry, rz)) + +if __name__ == "__main__": + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge) + check_symbolic_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old) + + if len(sys.argv) >= 2 and sys.argv[1] == "--exhaustive": + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_var", 0, 7, 5, formula_secp256k1_gej_add_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_var", 0, 7, 5, formula_secp256k1_gej_add_ge_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_zinv_var", 0, 7, 5, formula_secp256k1_gej_add_zinv_var, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge", 0, 7, 16, formula_secp256k1_gej_add_ge, 43) + check_exhaustive_jacobian_weierstrass("secp256k1_gej_add_ge_old [should fail]", 0, 7, 4, formula_secp256k1_gej_add_ge_old, 43) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage new file mode 100644 index 00000000..03ef2ec9 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/sage/weierstrass_prover.sage @@ -0,0 +1,264 @@ +# Prover implementation for Weierstrass curves of the form +# y^2 = x^3 + A * x + B, specifically with a = 0 and b = 7, with group laws +# operating on affine and Jacobian coordinates, including the point at infinity +# represented by a 4th variable in coordinates. + +load("group_prover.sage") + + +class affinepoint: + def __init__(self, x, y, infinity=0): + self.x = x + self.y = y + self.infinity = infinity + def __str__(self): + return "affinepoint(x=%s,y=%s,inf=%s)" % (self.x, self.y, self.infinity) + + +class jacobianpoint: + def __init__(self, x, y, z, infinity=0): + self.X = x + self.Y = y + self.Z = z + self.Infinity = infinity + def __str__(self): + return "jacobianpoint(X=%s,Y=%s,Z=%s,inf=%s)" % (self.X, self.Y, self.Z, self.Infinity) + + +def point_at_infinity(): + return jacobianpoint(1, 1, 1, 1) + + +def negate(p): + if p.__class__ == affinepoint: + return affinepoint(p.x, -p.y) + if p.__class__ == jacobianpoint: + return jacobianpoint(p.X, -p.Y, p.Z) + assert(False) + + +def on_weierstrass_curve(A, B, p): + """Return a set of zero-expressions for an affine point to be on the curve""" + return constraints(zero={p.x^3 + A*p.x + B - p.y^2: 'on_curve'}) + + +def tangential_to_weierstrass_curve(A, B, p12, p3): + """Return a set of zero-expressions for ((x12,y12),(x3,y3)) to be a line that is tangential to the curve at (x12,y12)""" + return constraints(zero={ + (p12.y - p3.y) * (p12.y * 2) - (p12.x^2 * 3 + A) * (p12.x - p3.x): 'tangential_to_curve' + }) + + +def colinear(p1, p2, p3): + """Return a set of zero-expressions for ((x1,y1),(x2,y2),(x3,y3)) to be collinear""" + return constraints(zero={ + (p1.y - p2.y) * (p1.x - p3.x) - (p1.y - p3.y) * (p1.x - p2.x): 'colinear_1', + (p2.y - p3.y) * (p2.x - p1.x) - (p2.y - p1.y) * (p2.x - p3.x): 'colinear_2', + (p3.y - p1.y) * (p3.x - p2.x) - (p3.y - p2.y) * (p3.x - p1.x): 'colinear_3' + }) + + +def good_affine_point(p): + return constraints(nonzero={p.x : 'nonzero_x', p.y : 'nonzero_y'}) + + +def good_jacobian_point(p): + return constraints(nonzero={p.X : 'nonzero_X', p.Y : 'nonzero_Y', p.Z^6 : 'nonzero_Z'}) + + +def good_point(p): + return constraints(nonzero={p.Z^6 : 'nonzero_X'}) + + +def finite(p, *affine_fns): + con = good_point(p) + constraints(zero={p.Infinity : 'finite_point'}) + if p.Z != 0: + return con + reduce(lambda a, b: a + b, (f(affinepoint(p.X / p.Z^2, p.Y / p.Z^3)) for f in affine_fns), con) + else: + return con + +def infinite(p): + return constraints(nonzero={p.Infinity : 'infinite_point'}) + + +def law_jacobian_weierstrass_add(A, B, pa, pb, pA, pB, pC): + """Check whether the passed set of coordinates is a valid Jacobian add, given assumptions""" + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(nonzero={pa.x - pb.x : 'different_x'})) + require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + + colinear(pa, pb, negate(pc)))) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_double(A, B, pa, pb, pA, pB, pC): + """Check whether the passed set of coordinates is a valid Jacobian doubling, given assumptions""" + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(zero={pa.x - pb.x : 'equal_x', pa.y - pb.y : 'equal_y'})) + require = (finite(pC, lambda pc: on_weierstrass_curve(A, B, pc) + + tangential_to_weierstrass_curve(A, B, pa, negate(pc)))) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_opposites(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + on_weierstrass_curve(A, B, pb) + + finite(pA) + + finite(pB) + + constraints(zero={pa.x - pb.x : 'equal_x', pa.y + pb.y : 'opposite_y'})) + require = infinite(pC) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_a(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pb) + + infinite(pA) + + finite(pB)) + require = finite(pC, lambda pc: constraints(zero={pc.x - pb.x : 'c.x=b.x', pc.y - pb.y : 'c.y=b.y'})) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_b(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + on_weierstrass_curve(A, B, pa) + + infinite(pB) + + finite(pA)) + require = finite(pC, lambda pc: constraints(zero={pc.x - pa.x : 'c.x=a.x', pc.y - pa.y : 'c.y=a.y'})) + return (assumeLaw, require) + + +def law_jacobian_weierstrass_add_infinite_ab(A, B, pa, pb, pA, pB, pC): + assumeLaw = (good_affine_point(pa) + + good_affine_point(pb) + + good_jacobian_point(pA) + + good_jacobian_point(pB) + + infinite(pA) + + infinite(pB)) + require = infinite(pC) + return (assumeLaw, require) + + +laws_jacobian_weierstrass = { + 'add': law_jacobian_weierstrass_add, + 'double': law_jacobian_weierstrass_double, + 'add_opposite': law_jacobian_weierstrass_add_opposites, + 'add_infinite_a': law_jacobian_weierstrass_add_infinite_a, + 'add_infinite_b': law_jacobian_weierstrass_add_infinite_b, + 'add_infinite_ab': law_jacobian_weierstrass_add_infinite_ab +} + + +def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p): + """Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field""" + F = Integers(p) + print "Formula %s on Z%i:" % (name, p) + points = [] + for x in xrange(0, p): + for y in xrange(0, p): + point = affinepoint(F(x), F(y)) + r, e = concrete_verify(on_weierstrass_curve(A, B, point)) + if r: + points.append(point) + + for za in xrange(1, p): + for zb in xrange(1, p): + for pa in points: + for pb in points: + for ia in xrange(2): + for ib in xrange(2): + pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia) + pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib) + for branch in xrange(0, branches): + assumeAssert, assumeBranch, pC = formula(branch, pA, pB) + pC.X = F(pC.X) + pC.Y = F(pC.Y) + pC.Z = F(pC.Z) + pC.Infinity = F(pC.Infinity) + r, e = concrete_verify(assumeAssert + assumeBranch) + if r: + match = False + for key in laws_jacobian_weierstrass: + assumeLaw, require = laws_jacobian_weierstrass[key](A, B, pa, pb, pA, pB, pC) + r, e = concrete_verify(assumeLaw) + if r: + if match: + print " multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity) + else: + match = True + r, e = concrete_verify(require) + if not r: + print " failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e) + print + + +def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC): + assumeLaw, require = f(A, B, pa, pb, pA, pB, pC) + return check_symbolic(R, assumeLaw, assumeAssert, assumeBranch, require) + +def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula): + """Verify an implementation of addition of Jacobian points on a Weierstrass curve symbolically""" + R. = PolynomialRing(QQ,8,order='invlex') + lift = lambda x: fastfrac(R,x) + ax = lift(ax) + ay = lift(ay) + Az = lift(Az) + bx = lift(bx) + by = lift(by) + Bz = lift(Bz) + Ai = lift(Ai) + Bi = lift(Bi) + + pa = affinepoint(ax, ay, Ai) + pb = affinepoint(bx, by, Bi) + pA = jacobianpoint(ax * Az^2, ay * Az^3, Az, Ai) + pB = jacobianpoint(bx * Bz^2, by * Bz^3, Bz, Bi) + + res = {} + + for key in laws_jacobian_weierstrass: + res[key] = [] + + print ("Formula " + name + ":") + count = 0 + for branch in xrange(branches): + assumeFormula, assumeBranch, pC = formula(branch, pA, pB) + pC.X = lift(pC.X) + pC.Y = lift(pC.Y) + pC.Z = lift(pC.Z) + pC.Infinity = lift(pC.Infinity) + + for key in laws_jacobian_weierstrass: + res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch)) + + for key in res: + print " %s:" % key + val = res[key] + for x in val: + if x[0] is not None: + print " branch %i: %s" % (x[1], x[0]) + + print diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s new file mode 100644 index 00000000..5df561f2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s @@ -0,0 +1,919 @@ +@ vim: set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab syntax=armasm: +/********************************************************************** + * Copyright (c) 2014 Wladimir J. van der Laan * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +/* +ARM implementation of field_10x26 inner loops. + +Note: + +- To avoid unnecessary loads and make use of available registers, two + 'passes' have every time been interleaved, with the odd passes accumulating c' and d' + which will be added to c and d respectively in the the even passes + +*/ + + .syntax unified + .arch armv7-a + @ eabi attributes - see readelf -A + .eabi_attribute 8, 1 @ Tag_ARM_ISA_use = yes + .eabi_attribute 9, 0 @ Tag_Thumb_ISA_use = no + .eabi_attribute 10, 0 @ Tag_FP_arch = none + .eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte + .eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP + .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Agressive Speed + .eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6 + .text + + @ Field constants + .set field_R0, 0x3d10 + .set field_R1, 0x400 + .set field_not_M, 0xfc000000 @ ~M = ~0x3ffffff + + .align 2 + .global secp256k1_fe_mul_inner + .type secp256k1_fe_mul_inner, %function + @ Arguments: + @ r0 r Restrict: can overlap with a, not with b + @ r1 a + @ r2 b + @ Stack (total 4+10*4 = 44) + @ sp + #0 saved 'r' pointer + @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 +secp256k1_fe_mul_inner: + stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} + sub sp, sp, #48 @ frame=44 + alignment + str r0, [sp, #0] @ save result address, we need it only at the end + + /****************************************** + * Main computation code. + ****************************************** + + Allocation: + r0,r14,r7,r8 scratch + r1 a (pointer) + r2 b (pointer) + r3:r4 c + r5:r6 d + r11:r12 c' + r9:r10 d' + + Note: do not write to r[] here, it may overlap with a[] + */ + + /* A - interleaved with B */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #9*4] @ b[9] + ldr r0, [r1, #1*4] @ a[1] + umull r5, r6, r7, r8 @ d = a[0] * b[9] + ldr r14, [r2, #8*4] @ b[8] + umull r9, r10, r0, r8 @ d' = a[1] * b[9] + ldr r7, [r1, #2*4] @ a[2] + umlal r5, r6, r0, r14 @ d += a[1] * b[8] + ldr r8, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r14 @ d' += a[2] * b[8] + ldr r0, [r1, #3*4] @ a[3] + umlal r5, r6, r7, r8 @ d += a[2] * b[7] + ldr r14, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r8 @ d' += a[3] * b[7] + ldr r7, [r1, #4*4] @ a[4] + umlal r5, r6, r0, r14 @ d += a[3] * b[6] + ldr r8, [r2, #5*4] @ b[5] + umlal r9, r10, r7, r14 @ d' += a[4] * b[6] + ldr r0, [r1, #5*4] @ a[5] + umlal r5, r6, r7, r8 @ d += a[4] * b[5] + ldr r14, [r2, #4*4] @ b[4] + umlal r9, r10, r0, r8 @ d' += a[5] * b[5] + ldr r7, [r1, #6*4] @ a[6] + umlal r5, r6, r0, r14 @ d += a[5] * b[4] + ldr r8, [r2, #3*4] @ b[3] + umlal r9, r10, r7, r14 @ d' += a[6] * b[4] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r8 @ d += a[6] * b[3] + ldr r14, [r2, #2*4] @ b[2] + umlal r9, r10, r0, r8 @ d' += a[7] * b[3] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r14 @ d += a[7] * b[2] + ldr r8, [r2, #1*4] @ b[1] + umlal r9, r10, r7, r14 @ d' += a[8] * b[2] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r8 @ d += a[8] * b[1] + ldr r14, [r2, #0*4] @ b[0] + umlal r9, r10, r0, r8 @ d' += a[9] * b[1] + ldr r7, [r1, #0*4] @ a[0] + umlal r5, r6, r0, r14 @ d += a[9] * b[0] + @ r7,r14 used in B + + bic r0, r5, field_not_M @ t9 = d & M + str r0, [sp, #4 + 4*9] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + /* B */ + umull r3, r4, r7, r14 @ c = a[0] * b[0] + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u0 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u0 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t0 = c & M + str r14, [sp, #4 + 0*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u0 * R1 + umlal r3, r4, r0, r14 + + /* C - interleaved with D */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #2*4] @ b[2] + ldr r14, [r2, #1*4] @ b[1] + umull r11, r12, r7, r8 @ c' = a[0] * b[2] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[1] * b[1] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[2] * b[0] + ldr r0, [r1, #3*4] @ a[3] + umlal r5, r6, r7, r14 @ d += a[2] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[3] * b[9] + ldr r7, [r1, #4*4] @ a[4] + umlal r5, r6, r0, r8 @ d += a[3] * b[8] + ldr r14, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r8 @ d' += a[4] * b[8] + ldr r0, [r1, #5*4] @ a[5] + umlal r5, r6, r7, r14 @ d += a[4] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r14 @ d' += a[5] * b[7] + ldr r7, [r1, #6*4] @ a[6] + umlal r5, r6, r0, r8 @ d += a[5] * b[6] + ldr r14, [r2, #5*4] @ b[5] + umlal r9, r10, r7, r8 @ d' += a[6] * b[6] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r14 @ d += a[6] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r9, r10, r0, r14 @ d' += a[7] * b[5] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r8 @ d += a[7] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r9, r10, r7, r8 @ d' += a[8] * b[4] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r9, r10, r0, r14 @ d' += a[9] * b[3] + umlal r5, r6, r0, r8 @ d += a[9] * b[2] + + bic r0, r5, field_not_M @ u1 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u1 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t1 = c & M + str r14, [sp, #4 + 1*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u1 * R1 + umlal r3, r4, r0, r14 + + /* D */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u2 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u2 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t2 = c & M + str r14, [sp, #4 + 2*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u2 * R1 + umlal r3, r4, r0, r14 + + /* E - interleaved with F */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #4*4] @ b[4] + umull r11, r12, r7, r8 @ c' = a[0] * b[4] + ldr r8, [r2, #3*4] @ b[3] + umlal r3, r4, r7, r8 @ c += a[0] * b[3] + ldr r7, [r1, #1*4] @ a[1] + umlal r11, r12, r7, r8 @ c' += a[1] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r3, r4, r7, r8 @ c += a[1] * b[2] + ldr r7, [r1, #2*4] @ a[2] + umlal r11, r12, r7, r8 @ c' += a[2] * b[2] + ldr r8, [r2, #1*4] @ b[1] + umlal r3, r4, r7, r8 @ c += a[2] * b[1] + ldr r7, [r1, #3*4] @ a[3] + umlal r11, r12, r7, r8 @ c' += a[3] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r3, r4, r7, r8 @ c += a[3] * b[0] + ldr r7, [r1, #4*4] @ a[4] + umlal r11, r12, r7, r8 @ c' += a[4] * b[0] + ldr r8, [r2, #9*4] @ b[9] + umlal r5, r6, r7, r8 @ d += a[4] * b[9] + ldr r7, [r1, #5*4] @ a[5] + umull r9, r10, r7, r8 @ d' = a[5] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umlal r5, r6, r7, r8 @ d += a[5] * b[8] + ldr r7, [r1, #6*4] @ a[6] + umlal r9, r10, r7, r8 @ d' += a[6] * b[8] + ldr r8, [r2, #7*4] @ b[7] + umlal r5, r6, r7, r8 @ d += a[6] * b[7] + ldr r7, [r1, #7*4] @ a[7] + umlal r9, r10, r7, r8 @ d' += a[7] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r5, r6, r7, r8 @ d += a[7] * b[6] + ldr r7, [r1, #8*4] @ a[8] + umlal r9, r10, r7, r8 @ d' += a[8] * b[6] + ldr r8, [r2, #5*4] @ b[5] + umlal r5, r6, r7, r8 @ d += a[8] * b[5] + ldr r7, [r1, #9*4] @ a[9] + umlal r9, r10, r7, r8 @ d' += a[9] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r5, r6, r7, r8 @ d += a[9] * b[4] + + bic r0, r5, field_not_M @ u3 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u3 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t3 = c & M + str r14, [sp, #4 + 3*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u3 * R1 + umlal r3, r4, r0, r14 + + /* F */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u4 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u4 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t4 = c & M + str r14, [sp, #4 + 4*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u4 * R1 + umlal r3, r4, r0, r14 + + /* G - interleaved with H */ + ldr r7, [r1, #0*4] @ a[0] + ldr r8, [r2, #6*4] @ b[6] + ldr r14, [r2, #5*4] @ b[5] + umull r11, r12, r7, r8 @ c' = a[0] * b[6] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r11, r12, r0, r14 @ c' += a[1] * b[5] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r11, r12, r7, r8 @ c' += a[2] * b[4] + ldr r0, [r1, #3*4] @ a[3] + umlal r3, r4, r7, r14 @ c += a[2] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r11, r12, r0, r14 @ c' += a[3] * b[3] + ldr r7, [r1, #4*4] @ a[4] + umlal r3, r4, r0, r8 @ c += a[3] * b[2] + ldr r14, [r2, #1*4] @ b[1] + umlal r11, r12, r7, r8 @ c' += a[4] * b[2] + ldr r0, [r1, #5*4] @ a[5] + umlal r3, r4, r7, r14 @ c += a[4] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[5] * b[1] + ldr r7, [r1, #6*4] @ a[6] + umlal r3, r4, r0, r8 @ c += a[5] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[6] * b[0] + ldr r0, [r1, #7*4] @ a[7] + umlal r5, r6, r7, r14 @ d += a[6] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[7] * b[9] + ldr r7, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r8 @ d += a[7] * b[8] + ldr r14, [r2, #7*4] @ b[7] + umlal r9, r10, r7, r8 @ d' += a[8] * b[8] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r9, r10, r0, r14 @ d' += a[9] * b[7] + umlal r5, r6, r0, r8 @ d += a[9] * b[6] + + bic r0, r5, field_not_M @ u5 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u5 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t5 = c & M + str r14, [sp, #4 + 5*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u5 * R1 + umlal r3, r4, r0, r14 + + /* H */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u6 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u6 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t6 = c & M + str r14, [sp, #4 + 6*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u6 * R1 + umlal r3, r4, r0, r14 + + /* I - interleaved with J */ + ldr r8, [r2, #8*4] @ b[8] + ldr r7, [r1, #0*4] @ a[0] + ldr r14, [r2, #7*4] @ b[7] + umull r11, r12, r7, r8 @ c' = a[0] * b[8] + ldr r0, [r1, #1*4] @ a[1] + umlal r3, r4, r7, r14 @ c += a[0] * b[7] + ldr r8, [r2, #6*4] @ b[6] + umlal r11, r12, r0, r14 @ c' += a[1] * b[7] + ldr r7, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r8 @ c += a[1] * b[6] + ldr r14, [r2, #5*4] @ b[5] + umlal r11, r12, r7, r8 @ c' += a[2] * b[6] + ldr r0, [r1, #3*4] @ a[3] + umlal r3, r4, r7, r14 @ c += a[2] * b[5] + ldr r8, [r2, #4*4] @ b[4] + umlal r11, r12, r0, r14 @ c' += a[3] * b[5] + ldr r7, [r1, #4*4] @ a[4] + umlal r3, r4, r0, r8 @ c += a[3] * b[4] + ldr r14, [r2, #3*4] @ b[3] + umlal r11, r12, r7, r8 @ c' += a[4] * b[4] + ldr r0, [r1, #5*4] @ a[5] + umlal r3, r4, r7, r14 @ c += a[4] * b[3] + ldr r8, [r2, #2*4] @ b[2] + umlal r11, r12, r0, r14 @ c' += a[5] * b[3] + ldr r7, [r1, #6*4] @ a[6] + umlal r3, r4, r0, r8 @ c += a[5] * b[2] + ldr r14, [r2, #1*4] @ b[1] + umlal r11, r12, r7, r8 @ c' += a[6] * b[2] + ldr r0, [r1, #7*4] @ a[7] + umlal r3, r4, r7, r14 @ c += a[6] * b[1] + ldr r8, [r2, #0*4] @ b[0] + umlal r11, r12, r0, r14 @ c' += a[7] * b[1] + ldr r7, [r1, #8*4] @ a[8] + umlal r3, r4, r0, r8 @ c += a[7] * b[0] + ldr r14, [r2, #9*4] @ b[9] + umlal r11, r12, r7, r8 @ c' += a[8] * b[0] + ldr r0, [r1, #9*4] @ a[9] + umlal r5, r6, r7, r14 @ d += a[8] * b[9] + ldr r8, [r2, #8*4] @ b[8] + umull r9, r10, r0, r14 @ d' = a[9] * b[9] + umlal r5, r6, r0, r8 @ d += a[9] * b[8] + + bic r0, r5, field_not_M @ u7 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u7 * R0 + umlal r3, r4, r0, r14 + + bic r14, r3, field_not_M @ t7 = c & M + str r14, [sp, #4 + 7*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u7 * R1 + umlal r3, r4, r0, r14 + + /* J */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u8 = d & M + str r0, [sp, #4 + 8*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u8 * R0 + umlal r3, r4, r0, r14 + + /****************************************** + * compute and write back result + ****************************************** + Allocation: + r0 r + r3:r4 c + r5:r6 d + r7 t0 + r8 t1 + r9 t2 + r11 u8 + r12 t9 + r1,r2,r10,r14 scratch + + Note: do not read from a[] after here, it may overlap with r[] + */ + ldr r0, [sp, #0] + add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 + ldmia r1, {r2,r7,r8,r9,r10,r11,r12} + add r1, r0, #3*4 + stmia r1, {r2,r7,r8,r9,r10} + + bic r2, r3, field_not_M @ r[8] = c & M + str r2, [r0, #8*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u8 * R1 + umlal r3, r4, r11, r14 + movw r14, field_R0 @ c += d * R0 + umlal r3, r4, r5, r14 + adds r3, r3, r12 @ c += t9 + adc r4, r4, #0 + + add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 + ldmia r1, {r7,r8,r9} + + ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) + str r2, [r0, #9*4] + mov r3, r3, lsr #22 @ c >>= 22 + orr r3, r3, r4, asl #10 + mov r4, r4, lsr #22 + movw r14, field_R1 << 4 @ c += d * (R1 << 4) + umlal r3, r4, r5, r14 + + movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) + umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) + adds r5, r5, r7 @ d.lo += t0 + mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) + adc r6, r6, 0 @ d.hi += carry + + bic r2, r5, field_not_M @ r[0] = d & M + str r2, [r0, #0*4] + + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) + umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) + adds r5, r5, r8 @ d.lo += t1 + adc r6, r6, #0 @ d.hi += carry + adds r5, r5, r1 @ d.lo += tmp.lo + mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) + adc r6, r6, r2 @ d.hi += carry + tmp.hi + + bic r2, r5, field_not_M @ r[1] = d & M + str r2, [r0, #1*4] + mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) + orr r5, r5, r6, asl #6 + + add r5, r5, r9 @ d += t2 + str r5, [r0, #2*4] @ r[2] = d + + add sp, sp, #48 + ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size secp256k1_fe_mul_inner, .-secp256k1_fe_mul_inner + + .align 2 + .global secp256k1_fe_sqr_inner + .type secp256k1_fe_sqr_inner, %function + @ Arguments: + @ r0 r Can overlap with a + @ r1 a + @ Stack (total 4+10*4 = 44) + @ sp + #0 saved 'r' pointer + @ sp + #4 + 4*X t0,t1,t2,t3,t4,t5,t6,t7,u8,t9 +secp256k1_fe_sqr_inner: + stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r14} + sub sp, sp, #48 @ frame=44 + alignment + str r0, [sp, #0] @ save result address, we need it only at the end + /****************************************** + * Main computation code. + ****************************************** + + Allocation: + r0,r14,r2,r7,r8 scratch + r1 a (pointer) + r3:r4 c + r5:r6 d + r11:r12 c' + r9:r10 d' + + Note: do not write to r[] here, it may overlap with a[] + */ + /* A interleaved with B */ + ldr r0, [r1, #1*4] @ a[1]*2 + ldr r7, [r1, #0*4] @ a[0] + mov r0, r0, asl #1 + ldr r14, [r1, #9*4] @ a[9] + umull r3, r4, r7, r7 @ c = a[0] * a[0] + ldr r8, [r1, #8*4] @ a[8] + mov r7, r7, asl #1 + umull r5, r6, r7, r14 @ d = a[0]*2 * a[9] + ldr r7, [r1, #2*4] @ a[2]*2 + umull r9, r10, r0, r14 @ d' = a[1]*2 * a[9] + ldr r14, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r8 @ d += a[1]*2 * a[8] + mov r7, r7, asl #1 + ldr r0, [r1, #3*4] @ a[3]*2 + umlal r9, r10, r7, r8 @ d' += a[2]*2 * a[8] + ldr r8, [r1, #6*4] @ a[6] + umlal r5, r6, r7, r14 @ d += a[2]*2 * a[7] + mov r0, r0, asl #1 + ldr r7, [r1, #4*4] @ a[4]*2 + umlal r9, r10, r0, r14 @ d' += a[3]*2 * a[7] + ldr r14, [r1, #5*4] @ a[5] + mov r7, r7, asl #1 + umlal r5, r6, r0, r8 @ d += a[3]*2 * a[6] + umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[6] + umlal r5, r6, r7, r14 @ d += a[4]*2 * a[5] + umlal r9, r10, r14, r14 @ d' += a[5] * a[5] + + bic r0, r5, field_not_M @ t9 = d & M + str r0, [sp, #4 + 9*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + /* B */ + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u0 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u0 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t0 = c & M + str r14, [sp, #4 + 0*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u0 * R1 + umlal r3, r4, r0, r14 + + /* C interleaved with D */ + ldr r0, [r1, #0*4] @ a[0]*2 + ldr r14, [r1, #1*4] @ a[1] + mov r0, r0, asl #1 + ldr r8, [r1, #2*4] @ a[2] + umlal r3, r4, r0, r14 @ c += a[0]*2 * a[1] + mov r7, r8, asl #1 @ a[2]*2 + umull r11, r12, r14, r14 @ c' = a[1] * a[1] + ldr r14, [r1, #9*4] @ a[9] + umlal r11, r12, r0, r8 @ c' += a[0]*2 * a[2] + ldr r0, [r1, #3*4] @ a[3]*2 + ldr r8, [r1, #8*4] @ a[8] + umlal r5, r6, r7, r14 @ d += a[2]*2 * a[9] + mov r0, r0, asl #1 + ldr r7, [r1, #4*4] @ a[4]*2 + umull r9, r10, r0, r14 @ d' = a[3]*2 * a[9] + ldr r14, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r8 @ d += a[3]*2 * a[8] + mov r7, r7, asl #1 + ldr r0, [r1, #5*4] @ a[5]*2 + umlal r9, r10, r7, r8 @ d' += a[4]*2 * a[8] + ldr r8, [r1, #6*4] @ a[6] + mov r0, r0, asl #1 + umlal r5, r6, r7, r14 @ d += a[4]*2 * a[7] + umlal r9, r10, r0, r14 @ d' += a[5]*2 * a[7] + umlal r5, r6, r0, r8 @ d += a[5]*2 * a[6] + umlal r9, r10, r8, r8 @ d' += a[6] * a[6] + + bic r0, r5, field_not_M @ u1 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u1 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t1 = c & M + str r14, [sp, #4 + 1*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u1 * R1 + umlal r3, r4, r0, r14 + + /* D */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u2 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u2 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t2 = c & M + str r14, [sp, #4 + 2*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u2 * R1 + umlal r3, r4, r0, r14 + + /* E interleaved with F */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + ldr r14, [r1, #2*4] @ a[2] + mov r7, r7, asl #1 + ldr r8, [r1, #3*4] @ a[3] + ldr r2, [r1, #4*4] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[3] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[4] + mov r2, r2, asl #1 @ a[4]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[3] + ldr r8, [r1, #9*4] @ a[9] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[2] + ldr r0, [r1, #5*4] @ a[5]*2 + umlal r11, r12, r14, r14 @ c' += a[2] * a[2] + ldr r14, [r1, #8*4] @ a[8] + mov r0, r0, asl #1 + umlal r5, r6, r2, r8 @ d += a[4]*2 * a[9] + ldr r7, [r1, #6*4] @ a[6]*2 + umull r9, r10, r0, r8 @ d' = a[5]*2 * a[9] + mov r7, r7, asl #1 + ldr r8, [r1, #7*4] @ a[7] + umlal r5, r6, r0, r14 @ d += a[5]*2 * a[8] + umlal r9, r10, r7, r14 @ d' += a[6]*2 * a[8] + umlal r5, r6, r7, r8 @ d += a[6]*2 * a[7] + umlal r9, r10, r8, r8 @ d' += a[7] * a[7] + + bic r0, r5, field_not_M @ u3 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u3 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t3 = c & M + str r14, [sp, #4 + 3*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u3 * R1 + umlal r3, r4, r0, r14 + + /* F */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u4 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u4 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t4 = c & M + str r14, [sp, #4 + 4*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u4 * R1 + umlal r3, r4, r0, r14 + + /* G interleaved with H */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + mov r7, r7, asl #1 + ldr r8, [r1, #5*4] @ a[5] + ldr r2, [r1, #6*4] @ a[6] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[5] + ldr r14, [r1, #4*4] @ a[4] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[6] + ldr r7, [r1, #2*4] @ a[2]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[5] + mov r7, r7, asl #1 + ldr r8, [r1, #3*4] @ a[3] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[4] + mov r0, r2, asl #1 @ a[6]*2 + umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[4] + ldr r14, [r1, #9*4] @ a[9] + umlal r3, r4, r7, r8 @ c += a[2]*2 * a[3] + ldr r7, [r1, #7*4] @ a[7]*2 + umlal r11, r12, r8, r8 @ c' += a[3] * a[3] + mov r7, r7, asl #1 + ldr r8, [r1, #8*4] @ a[8] + umlal r5, r6, r0, r14 @ d += a[6]*2 * a[9] + umull r9, r10, r7, r14 @ d' = a[7]*2 * a[9] + umlal r5, r6, r7, r8 @ d += a[7]*2 * a[8] + umlal r9, r10, r8, r8 @ d' += a[8] * a[8] + + bic r0, r5, field_not_M @ u5 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u5 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t5 = c & M + str r14, [sp, #4 + 5*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u5 * R1 + umlal r3, r4, r0, r14 + + /* H */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + adds r5, r5, r9 @ d += d' + adc r6, r6, r10 + + bic r0, r5, field_not_M @ u6 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u6 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t6 = c & M + str r14, [sp, #4 + 6*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u6 * R1 + umlal r3, r4, r0, r14 + + /* I interleaved with J */ + ldr r7, [r1, #0*4] @ a[0]*2 + ldr r0, [r1, #1*4] @ a[1]*2 + mov r7, r7, asl #1 + ldr r8, [r1, #7*4] @ a[7] + ldr r2, [r1, #8*4] @ a[8] + umlal r3, r4, r7, r8 @ c += a[0]*2 * a[7] + ldr r14, [r1, #6*4] @ a[6] + mov r0, r0, asl #1 + umull r11, r12, r7, r2 @ c' = a[0]*2 * a[8] + ldr r7, [r1, #2*4] @ a[2]*2 + umlal r11, r12, r0, r8 @ c' += a[1]*2 * a[7] + ldr r8, [r1, #5*4] @ a[5] + umlal r3, r4, r0, r14 @ c += a[1]*2 * a[6] + ldr r0, [r1, #3*4] @ a[3]*2 + mov r7, r7, asl #1 + umlal r11, r12, r7, r14 @ c' += a[2]*2 * a[6] + ldr r14, [r1, #4*4] @ a[4] + mov r0, r0, asl #1 + umlal r3, r4, r7, r8 @ c += a[2]*2 * a[5] + mov r2, r2, asl #1 @ a[8]*2 + umlal r11, r12, r0, r8 @ c' += a[3]*2 * a[5] + umlal r3, r4, r0, r14 @ c += a[3]*2 * a[4] + umlal r11, r12, r14, r14 @ c' += a[4] * a[4] + ldr r8, [r1, #9*4] @ a[9] + umlal r5, r6, r2, r8 @ d += a[8]*2 * a[9] + @ r8 will be used in J + + bic r0, r5, field_not_M @ u7 = d & M + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u7 * R0 + umlal r3, r4, r0, r14 + bic r14, r3, field_not_M @ t7 = c & M + str r14, [sp, #4 + 7*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u7 * R1 + umlal r3, r4, r0, r14 + + /* J */ + adds r3, r3, r11 @ c += c' + adc r4, r4, r12 + umlal r5, r6, r8, r8 @ d += a[9] * a[9] + + bic r0, r5, field_not_M @ u8 = d & M + str r0, [sp, #4 + 8*4] + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + movw r14, field_R0 @ c += u8 * R0 + umlal r3, r4, r0, r14 + + /****************************************** + * compute and write back result + ****************************************** + Allocation: + r0 r + r3:r4 c + r5:r6 d + r7 t0 + r8 t1 + r9 t2 + r11 u8 + r12 t9 + r1,r2,r10,r14 scratch + + Note: do not read from a[] after here, it may overlap with r[] + */ + ldr r0, [sp, #0] + add r1, sp, #4 + 3*4 @ r[3..7] = t3..7, r11=u8, r12=t9 + ldmia r1, {r2,r7,r8,r9,r10,r11,r12} + add r1, r0, #3*4 + stmia r1, {r2,r7,r8,r9,r10} + + bic r2, r3, field_not_M @ r[8] = c & M + str r2, [r0, #8*4] + mov r3, r3, lsr #26 @ c >>= 26 + orr r3, r3, r4, asl #6 + mov r4, r4, lsr #26 + mov r14, field_R1 @ c += u8 * R1 + umlal r3, r4, r11, r14 + movw r14, field_R0 @ c += d * R0 + umlal r3, r4, r5, r14 + adds r3, r3, r12 @ c += t9 + adc r4, r4, #0 + + add r1, sp, #4 + 0*4 @ r7,r8,r9 = t0,t1,t2 + ldmia r1, {r7,r8,r9} + + ubfx r2, r3, #0, #22 @ r[9] = c & (M >> 4) + str r2, [r0, #9*4] + mov r3, r3, lsr #22 @ c >>= 22 + orr r3, r3, r4, asl #10 + mov r4, r4, lsr #22 + movw r14, field_R1 << 4 @ c += d * (R1 << 4) + umlal r3, r4, r5, r14 + + movw r14, field_R0 >> 4 @ d = c * (R0 >> 4) + t0 (64x64 multiply+add) + umull r5, r6, r3, r14 @ d = c.lo * (R0 >> 4) + adds r5, r5, r7 @ d.lo += t0 + mla r6, r14, r4, r6 @ d.hi += c.hi * (R0 >> 4) + adc r6, r6, 0 @ d.hi += carry + + bic r2, r5, field_not_M @ r[0] = d & M + str r2, [r0, #0*4] + + mov r5, r5, lsr #26 @ d >>= 26 + orr r5, r5, r6, asl #6 + mov r6, r6, lsr #26 + + movw r14, field_R1 >> 4 @ d += c * (R1 >> 4) + t1 (64x64 multiply+add) + umull r1, r2, r3, r14 @ tmp = c.lo * (R1 >> 4) + adds r5, r5, r8 @ d.lo += t1 + adc r6, r6, #0 @ d.hi += carry + adds r5, r5, r1 @ d.lo += tmp.lo + mla r2, r14, r4, r2 @ tmp.hi += c.hi * (R1 >> 4) + adc r6, r6, r2 @ d.hi += carry + tmp.hi + + bic r2, r5, field_not_M @ r[1] = d & M + str r2, [r0, #1*4] + mov r5, r5, lsr #26 @ d >>= 26 (ignore hi) + orr r5, r5, r6, asl #6 + + add r5, r5, r9 @ d += t2 + str r5, [r0, #2*4] @ r[2] = d + + add sp, sp, #48 + ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} + .size secp256k1_fe_sqr_inner, .-secp256k1_fe_sqr_inner + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h new file mode 100644 index 00000000..c4c16eb7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/basic-config.h @@ -0,0 +1,32 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_BASIC_CONFIG_ +#define _SECP256K1_BASIC_CONFIG_ + +#ifdef USE_BASIC_CONFIG + +#undef USE_ASM_X86_64 +#undef USE_ENDOMORPHISM +#undef USE_FIELD_10X26 +#undef USE_FIELD_5X52 +#undef USE_FIELD_INV_BUILTIN +#undef USE_FIELD_INV_NUM +#undef USE_NUM_GMP +#undef USE_NUM_NONE +#undef USE_SCALAR_4X64 +#undef USE_SCALAR_8X32 +#undef USE_SCALAR_INV_BUILTIN +#undef USE_SCALAR_INV_NUM + +#define USE_NUM_NONE 1 +#define USE_FIELD_INV_BUILTIN 1 +#define USE_SCALAR_INV_BUILTIN 1 +#define USE_FIELD_10X26 1 +#define USE_SCALAR_8X32 1 + +#endif // USE_BASIC_CONFIG +#endif // _SECP256K1_BASIC_CONFIG_ diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h new file mode 100644 index 00000000..3a71b4aa --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench.h @@ -0,0 +1,66 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_BENCH_H_ +#define _SECP256K1_BENCH_H_ + +#include +#include +#include "sys/time.h" + +static double gettimedouble(void) { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_usec * 0.000001 + tv.tv_sec; +} + +void print_number(double x) { + double y = x; + int c = 0; + if (y < 0.0) { + y = -y; + } + while (y < 100.0) { + y *= 10.0; + c++; + } + printf("%.*f", c, x); +} + +void run_benchmark(char *name, void (*benchmark)(void*), void (*setup)(void*), void (*teardown)(void*), void* data, int count, int iter) { + int i; + double min = HUGE_VAL; + double sum = 0.0; + double max = 0.0; + for (i = 0; i < count; i++) { + double begin, total; + if (setup != NULL) { + setup(data); + } + begin = gettimedouble(); + benchmark(data); + total = gettimedouble() - begin; + if (teardown != NULL) { + teardown(data); + } + if (total < min) { + min = total; + } + if (total > max) { + max = total; + } + sum += total; + } + printf("%s: min ", name); + print_number(min * 1000000.0 / iter); + printf("us / avg "); + print_number((sum / count) * 1000000.0 / iter); + printf("us / max "); + print_number(max * 1000000.0 / iter); + printf("us\n"); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c new file mode 100644 index 00000000..cde5e2db --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_ecdh.c @@ -0,0 +1,54 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include + +#include "include/secp256k1.h" +#include "include/secp256k1_ecdh.h" +#include "util.h" +#include "bench.h" + +typedef struct { + secp256k1_context *ctx; + secp256k1_pubkey point; + unsigned char scalar[32]; +} bench_ecdh_t; + +static void bench_ecdh_setup(void* arg) { + int i; + bench_ecdh_t *data = (bench_ecdh_t*)arg; + const unsigned char point[] = { + 0x03, + 0x54, 0x94, 0xc1, 0x5d, 0x32, 0x09, 0x97, 0x06, + 0xc2, 0x39, 0x5f, 0x94, 0x34, 0x87, 0x45, 0xfd, + 0x75, 0x7c, 0xe3, 0x0e, 0x4e, 0x8c, 0x90, 0xfb, + 0xa2, 0xba, 0xd1, 0x84, 0xf8, 0x83, 0xc6, 0x9f + }; + + /* create a context with no capabilities */ + data->ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); + for (i = 0; i < 32; i++) { + data->scalar[i] = i + 1; + } + CHECK(secp256k1_ec_pubkey_parse(data->ctx, &data->point, point, sizeof(point)) == 1); +} + +static void bench_ecdh(void* arg) { + int i; + unsigned char res[32]; + bench_ecdh_t *data = (bench_ecdh_t*)arg; + + for (i = 0; i < 20000; i++) { + CHECK(secp256k1_ecdh(data->ctx, res, &data->point, data->scalar) == 1); + } +} + +int main(void) { + bench_ecdh_t data; + + run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, 20000); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c new file mode 100644 index 00000000..0809f77b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_internal.c @@ -0,0 +1,382 @@ +/********************************************************************** + * Copyright (c) 2014-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ +#include + +#include "include/secp256k1.h" + +#include "util.h" +#include "hash_impl.h" +#include "num_impl.h" +#include "field_impl.h" +#include "group_impl.h" +#include "scalar_impl.h" +#include "ecmult_const_impl.h" +#include "ecmult_impl.h" +#include "bench.h" +#include "secp256k1.c" + +typedef struct { + secp256k1_scalar scalar_x, scalar_y; + secp256k1_fe fe_x, fe_y; + secp256k1_ge ge_x, ge_y; + secp256k1_gej gej_x, gej_y; + unsigned char data[64]; + int wnaf[256]; +} bench_inv_t; + +void bench_setup(void* arg) { + bench_inv_t *data = (bench_inv_t*)arg; + + static const unsigned char init_x[32] = { + 0x02, 0x03, 0x05, 0x07, 0x0b, 0x0d, 0x11, 0x13, + 0x17, 0x1d, 0x1f, 0x25, 0x29, 0x2b, 0x2f, 0x35, + 0x3b, 0x3d, 0x43, 0x47, 0x49, 0x4f, 0x53, 0x59, + 0x61, 0x65, 0x67, 0x6b, 0x6d, 0x71, 0x7f, 0x83 + }; + + static const unsigned char init_y[32] = { + 0x82, 0x83, 0x85, 0x87, 0x8b, 0x8d, 0x81, 0x83, + 0x97, 0xad, 0xaf, 0xb5, 0xb9, 0xbb, 0xbf, 0xc5, + 0xdb, 0xdd, 0xe3, 0xe7, 0xe9, 0xef, 0xf3, 0xf9, + 0x11, 0x15, 0x17, 0x1b, 0x1d, 0xb1, 0xbf, 0xd3 + }; + + secp256k1_scalar_set_b32(&data->scalar_x, init_x, NULL); + secp256k1_scalar_set_b32(&data->scalar_y, init_y, NULL); + secp256k1_fe_set_b32(&data->fe_x, init_x); + secp256k1_fe_set_b32(&data->fe_y, init_y); + CHECK(secp256k1_ge_set_xo_var(&data->ge_x, &data->fe_x, 0)); + CHECK(secp256k1_ge_set_xo_var(&data->ge_y, &data->fe_y, 1)); + secp256k1_gej_set_ge(&data->gej_x, &data->ge_x); + secp256k1_gej_set_ge(&data->gej_y, &data->ge_y); + memcpy(data->data, init_x, 32); + memcpy(data->data + 32, init_y, 32); +} + +void bench_scalar_add(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000000; i++) { + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +void bench_scalar_negate(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000000; i++) { + secp256k1_scalar_negate(&data->scalar_x, &data->scalar_x); + } +} + +void bench_scalar_sqr(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_scalar_sqr(&data->scalar_x, &data->scalar_x); + } +} + +void bench_scalar_mul(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_scalar_mul(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +#ifdef USE_ENDOMORPHISM +void bench_scalar_split(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_scalar l, r; + secp256k1_scalar_split_lambda(&l, &r, &data->scalar_x); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} +#endif + +void bench_scalar_inverse(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000; i++) { + secp256k1_scalar_inverse(&data->scalar_x, &data->scalar_x); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +void bench_scalar_inverse_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000; i++) { + secp256k1_scalar_inverse_var(&data->scalar_x, &data->scalar_x); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +void bench_field_normalize(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000000; i++) { + secp256k1_fe_normalize(&data->fe_x); + } +} + +void bench_field_normalize_weak(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 2000000; i++) { + secp256k1_fe_normalize_weak(&data->fe_x); + } +} + +void bench_field_mul(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_fe_mul(&data->fe_x, &data->fe_x, &data->fe_y); + } +} + +void bench_field_sqr(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_fe_sqr(&data->fe_x, &data->fe_x); + } +} + +void bench_field_inverse(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_fe_inv(&data->fe_x, &data->fe_x); + secp256k1_fe_add(&data->fe_x, &data->fe_y); + } +} + +void bench_field_inverse_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_fe_inv_var(&data->fe_x, &data->fe_x); + secp256k1_fe_add(&data->fe_x, &data->fe_y); + } +} + +void bench_field_sqrt(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_fe_sqrt(&data->fe_x, &data->fe_x); + secp256k1_fe_add(&data->fe_x, &data->fe_y); + } +} + +void bench_group_double_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_gej_double_var(&data->gej_x, &data->gej_x, NULL); + } +} + +void bench_group_add_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_gej_add_var(&data->gej_x, &data->gej_x, &data->gej_y, NULL); + } +} + +void bench_group_add_affine(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_gej_add_ge(&data->gej_x, &data->gej_x, &data->ge_y); + } +} + +void bench_group_add_affine_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 200000; i++) { + secp256k1_gej_add_ge_var(&data->gej_x, &data->gej_x, &data->ge_y, NULL); + } +} + +void bench_group_jacobi_var(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_gej_has_quad_y_var(&data->gej_x); + } +} + +void bench_ecmult_wnaf(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_ecmult_wnaf(data->wnaf, 256, &data->scalar_x, WINDOW_A); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + +void bench_wnaf_const(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_wnaf_const(data->wnaf, data->scalar_x, WINDOW_A); + secp256k1_scalar_add(&data->scalar_x, &data->scalar_x, &data->scalar_y); + } +} + + +void bench_sha256(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_sha256_t sha; + + for (i = 0; i < 20000; i++) { + secp256k1_sha256_initialize(&sha); + secp256k1_sha256_write(&sha, data->data, 32); + secp256k1_sha256_finalize(&sha, data->data); + } +} + +void bench_hmac_sha256(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_hmac_sha256_t hmac; + + for (i = 0; i < 20000; i++) { + secp256k1_hmac_sha256_initialize(&hmac, data->data, 32); + secp256k1_hmac_sha256_write(&hmac, data->data, 32); + secp256k1_hmac_sha256_finalize(&hmac, data->data); + } +} + +void bench_rfc6979_hmac_sha256(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_rfc6979_hmac_sha256_t rng; + + for (i = 0; i < 20000; i++) { + secp256k1_rfc6979_hmac_sha256_initialize(&rng, data->data, 64); + secp256k1_rfc6979_hmac_sha256_generate(&rng, data->data, 32); + } +} + +void bench_context_verify(void* arg) { + int i; + (void)arg; + for (i = 0; i < 20; i++) { + secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY)); + } +} + +void bench_context_sign(void* arg) { + int i; + (void)arg; + for (i = 0; i < 200; i++) { + secp256k1_context_destroy(secp256k1_context_create(SECP256K1_CONTEXT_SIGN)); + } +} + +#ifndef USE_NUM_NONE +void bench_num_jacobi(void* arg) { + int i; + bench_inv_t *data = (bench_inv_t*)arg; + secp256k1_num nx, norder; + + secp256k1_scalar_get_num(&nx, &data->scalar_x); + secp256k1_scalar_order_get_num(&norder); + secp256k1_scalar_get_num(&norder, &data->scalar_y); + + for (i = 0; i < 200000; i++) { + secp256k1_num_jacobi(&nx, &norder); + } +} +#endif + +int have_flag(int argc, char** argv, char *flag) { + char** argm = argv + argc; + argv++; + if (argv == argm) { + return 1; + } + while (argv != NULL && argv != argm) { + if (strcmp(*argv, flag) == 0) { + return 1; + } + argv++; + } + return 0; +} + +int main(int argc, char **argv) { + bench_inv_t data; + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, 2000000); + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, 2000000); + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "sqr")) run_benchmark("scalar_sqr", bench_scalar_sqr, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "mul")) run_benchmark("scalar_mul", bench_scalar_mul, bench_setup, NULL, &data, 10, 200000); +#ifdef USE_ENDOMORPHISM + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "split")) run_benchmark("scalar_split", bench_scalar_split, bench_setup, NULL, &data, 10, 20000); +#endif + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse", bench_scalar_inverse, bench_setup, NULL, &data, 10, 2000); + if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "inverse")) run_benchmark("scalar_inverse_var", bench_scalar_inverse_var, bench_setup, NULL, &data, 10, 2000); + + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize", bench_field_normalize, bench_setup, NULL, &data, 10, 2000000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "normalize")) run_benchmark("field_normalize_weak", bench_field_normalize_weak, bench_setup, NULL, &data, 10, 2000000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqr")) run_benchmark("field_sqr", bench_field_sqr, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "mul")) run_benchmark("field_mul", bench_field_mul, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse", bench_field_inverse, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "inverse")) run_benchmark("field_inverse_var", bench_field_inverse_var, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "field") || have_flag(argc, argv, "sqrt")) run_benchmark("field_sqrt", bench_field_sqrt, bench_setup, NULL, &data, 10, 20000); + + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "double")) run_benchmark("group_double_var", bench_group_double_var, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, 200000); + if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, 20000); + + if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000); + + if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "sha256")) run_benchmark("hash_sha256", bench_sha256, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "hmac")) run_benchmark("hash_hmac_sha256", bench_hmac_sha256, bench_setup, NULL, &data, 10, 20000); + if (have_flag(argc, argv, "hash") || have_flag(argc, argv, "rng6979")) run_benchmark("hash_rfc6979_hmac_sha256", bench_rfc6979_hmac_sha256, bench_setup, NULL, &data, 10, 20000); + + if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 20); + if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 200); + +#ifndef USE_NUM_NONE + if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, 200000); +#endif + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c new file mode 100644 index 00000000..6489378c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_recover.c @@ -0,0 +1,60 @@ +/********************************************************************** + * Copyright (c) 2014-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include "include/secp256k1.h" +#include "include/secp256k1_recovery.h" +#include "util.h" +#include "bench.h" + +typedef struct { + secp256k1_context *ctx; + unsigned char msg[32]; + unsigned char sig[64]; +} bench_recover_t; + +void bench_recover(void* arg) { + int i; + bench_recover_t *data = (bench_recover_t*)arg; + secp256k1_pubkey pubkey; + unsigned char pubkeyc[33]; + + for (i = 0; i < 20000; i++) { + int j; + size_t pubkeylen = 33; + secp256k1_ecdsa_recoverable_signature sig; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(data->ctx, &sig, data->sig, i % 2)); + CHECK(secp256k1_ecdsa_recover(data->ctx, &pubkey, &sig, data->msg)); + CHECK(secp256k1_ec_pubkey_serialize(data->ctx, pubkeyc, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); + for (j = 0; j < 32; j++) { + data->sig[j + 32] = data->msg[j]; /* Move former message to S. */ + data->msg[j] = data->sig[j]; /* Move former R to message. */ + data->sig[j] = pubkeyc[j + 1]; /* Move recovered pubkey X coordinate to R (which must be a valid X coordinate). */ + } + } +} + +void bench_recover_setup(void* arg) { + int i; + bench_recover_t *data = (bench_recover_t*)arg; + + for (i = 0; i < 32; i++) { + data->msg[i] = 1 + i; + } + for (i = 0; i < 64; i++) { + data->sig[i] = 65 + i; + } +} + +int main(void) { + bench_recover_t data; + + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + + run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, 20000); + + secp256k1_context_destroy(data.ctx); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c new file mode 100644 index 00000000..5f137dda --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_schnorr_verify.c @@ -0,0 +1,73 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include + +#include "include/secp256k1.h" +#include "include/secp256k1_schnorr.h" +#include "util.h" +#include "bench.h" + +typedef struct { + unsigned char key[32]; + unsigned char sig[64]; + unsigned char pubkey[33]; + size_t pubkeylen; +} benchmark_schnorr_sig_t; + +typedef struct { + secp256k1_context *ctx; + unsigned char msg[32]; + benchmark_schnorr_sig_t sigs[64]; + int numsigs; +} benchmark_schnorr_verify_t; + +static void benchmark_schnorr_init(void* arg) { + int i, k; + benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; + + for (i = 0; i < 32; i++) { + data->msg[i] = 1 + i; + } + for (k = 0; k < data->numsigs; k++) { + secp256k1_pubkey pubkey; + for (i = 0; i < 32; i++) { + data->sigs[k].key[i] = 33 + i + k; + } + secp256k1_schnorr_sign(data->ctx, data->sigs[k].sig, data->msg, data->sigs[k].key, NULL, NULL); + data->sigs[k].pubkeylen = 33; + CHECK(secp256k1_ec_pubkey_create(data->ctx, &pubkey, data->sigs[k].key)); + CHECK(secp256k1_ec_pubkey_serialize(data->ctx, data->sigs[k].pubkey, &data->sigs[k].pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)); + } +} + +static void benchmark_schnorr_verify(void* arg) { + int i; + benchmark_schnorr_verify_t* data = (benchmark_schnorr_verify_t*)arg; + + for (i = 0; i < 20000 / data->numsigs; i++) { + secp256k1_pubkey pubkey; + data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); + CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->sigs[0].pubkey, data->sigs[0].pubkeylen)); + CHECK(secp256k1_schnorr_verify(data->ctx, data->sigs[0].sig, data->msg, &pubkey) == ((i & 0xFF) == 0)); + data->sigs[0].sig[(i >> 8) % 64] ^= (i & 0xFF); + } +} + + + +int main(void) { + benchmark_schnorr_verify_t data; + + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + data.numsigs = 1; + run_benchmark("schnorr_verify", benchmark_schnorr_verify, benchmark_schnorr_init, NULL, &data, 10, 20000); + + secp256k1_context_destroy(data.ctx); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c new file mode 100644 index 00000000..ed7224d7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_sign.c @@ -0,0 +1,56 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include "include/secp256k1.h" +#include "util.h" +#include "bench.h" + +typedef struct { + secp256k1_context* ctx; + unsigned char msg[32]; + unsigned char key[32]; +} bench_sign_t; + +static void bench_sign_setup(void* arg) { + int i; + bench_sign_t *data = (bench_sign_t*)arg; + + for (i = 0; i < 32; i++) { + data->msg[i] = i + 1; + } + for (i = 0; i < 32; i++) { + data->key[i] = i + 65; + } +} + +static void bench_sign(void* arg) { + int i; + bench_sign_t *data = (bench_sign_t*)arg; + + unsigned char sig[74]; + for (i = 0; i < 20000; i++) { + size_t siglen = 74; + int j; + secp256k1_ecdsa_signature signature; + CHECK(secp256k1_ecdsa_sign(data->ctx, &signature, data->msg, data->key, NULL, NULL)); + CHECK(secp256k1_ecdsa_signature_serialize_der(data->ctx, sig, &siglen, &signature)); + for (j = 0; j < 32; j++) { + data->msg[j] = sig[j]; + data->key[j] = sig[j + 32]; + } + } +} + +int main(void) { + bench_sign_t data; + + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + + run_benchmark("ecdsa_sign", bench_sign, bench_sign_setup, NULL, &data, 10, 20000); + + secp256k1_context_destroy(data.ctx); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c new file mode 100644 index 00000000..418defa0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/bench_verify.c @@ -0,0 +1,112 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include +#include + +#include "include/secp256k1.h" +#include "util.h" +#include "bench.h" + +#ifdef ENABLE_OPENSSL_TESTS +#include +#include +#include +#endif + +typedef struct { + secp256k1_context *ctx; + unsigned char msg[32]; + unsigned char key[32]; + unsigned char sig[72]; + size_t siglen; + unsigned char pubkey[33]; + size_t pubkeylen; +#ifdef ENABLE_OPENSSL_TESTS + EC_GROUP* ec_group; +#endif +} benchmark_verify_t; + +static void benchmark_verify(void* arg) { + int i; + benchmark_verify_t* data = (benchmark_verify_t*)arg; + + for (i = 0; i < 20000; i++) { + secp256k1_pubkey pubkey; + secp256k1_ecdsa_signature sig; + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pubkey, data->pubkey, data->pubkeylen) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(data->ctx, &sig, data->sig, data->siglen) == 1); + CHECK(secp256k1_ecdsa_verify(data->ctx, &sig, data->msg, &pubkey) == (i == 0)); + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + } +} + +#ifdef ENABLE_OPENSSL_TESTS +static void benchmark_verify_openssl(void* arg) { + int i; + benchmark_verify_t* data = (benchmark_verify_t*)arg; + + for (i = 0; i < 20000; i++) { + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + { + EC_KEY *pkey = EC_KEY_new(); + const unsigned char *pubkey = &data->pubkey[0]; + int result; + + CHECK(pkey != NULL); + result = EC_KEY_set_group(pkey, data->ec_group); + CHECK(result); + result = (o2i_ECPublicKey(&pkey, &pubkey, data->pubkeylen)) != NULL; + CHECK(result); + result = ECDSA_verify(0, &data->msg[0], sizeof(data->msg), &data->sig[0], data->siglen, pkey) == (i == 0); + CHECK(result); + EC_KEY_free(pkey); + } + data->sig[data->siglen - 1] ^= (i & 0xFF); + data->sig[data->siglen - 2] ^= ((i >> 8) & 0xFF); + data->sig[data->siglen - 3] ^= ((i >> 16) & 0xFF); + } +} +#endif + +int main(void) { + int i; + secp256k1_pubkey pubkey; + secp256k1_ecdsa_signature sig; + benchmark_verify_t data; + + data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + for (i = 0; i < 32; i++) { + data.msg[i] = 1 + i; + } + for (i = 0; i < 32; i++) { + data.key[i] = 33 + i; + } + data.siglen = 72; + CHECK(secp256k1_ecdsa_sign(data.ctx, &sig, data.msg, data.key, NULL, NULL)); + CHECK(secp256k1_ecdsa_signature_serialize_der(data.ctx, data.sig, &data.siglen, &sig)); + CHECK(secp256k1_ec_pubkey_create(data.ctx, &pubkey, data.key)); + data.pubkeylen = 33; + CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + + run_benchmark("ecdsa_verify", benchmark_verify, NULL, NULL, &data, 10, 20000); +#ifdef ENABLE_OPENSSL_TESTS + data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); + run_benchmark("ecdsa_verify_openssl", benchmark_verify_openssl, NULL, NULL, &data, 10, 20000); + EC_GROUP_free(data.ec_group); +#endif + + secp256k1_context_destroy(data.ctx); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h new file mode 100644 index 00000000..54ae101b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa.h @@ -0,0 +1,21 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECDSA_ +#define _SECP256K1_ECDSA_ + +#include + +#include "scalar.h" +#include "group.h" +#include "ecmult.h" + +static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *r, secp256k1_scalar *s, const unsigned char *sig, size_t size); +static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar *r, const secp256k1_scalar *s); +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar* r, const secp256k1_scalar* s, const secp256k1_ge *pubkey, const secp256k1_scalar *message); +static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h new file mode 100644 index 00000000..453bb118 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecdsa_impl.h @@ -0,0 +1,315 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + + +#ifndef _SECP256K1_ECDSA_IMPL_H_ +#define _SECP256K1_ECDSA_IMPL_H_ + +#include "scalar.h" +#include "field.h" +#include "group.h" +#include "ecmult.h" +#include "ecmult_gen.h" +#include "ecdsa.h" + +/** Group order for secp256k1 defined as 'n' in "Standards for Efficient Cryptography" (SEC2) 2.7.1 + * sage: for t in xrange(1023, -1, -1): + * .. p = 2**256 - 2**32 - t + * .. if p.is_prime(): + * .. print '%x'%p + * .. break + * 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f' + * sage: a = 0 + * sage: b = 7 + * sage: F = FiniteField (p) + * sage: '%x' % (EllipticCurve ([F (a), F (b)]).order()) + * 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141' + */ +static const secp256k1_fe secp256k1_ecdsa_const_order_as_fe = SECP256K1_FE_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0xBAAEDCE6UL, 0xAF48A03BUL, 0xBFD25E8CUL, 0xD0364141UL +); + +/** Difference between field and order, values 'p' and 'n' values defined in + * "Standards for Efficient Cryptography" (SEC2) 2.7.1. + * sage: p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F + * sage: a = 0 + * sage: b = 7 + * sage: F = FiniteField (p) + * sage: '%x' % (p - EllipticCurve ([F (a), F (b)]).order()) + * '14551231950b75fc4402da1722fc9baee' + */ +static const secp256k1_fe secp256k1_ecdsa_const_p_minus_order = SECP256K1_FE_CONST( + 0, 0, 0, 1, 0x45512319UL, 0x50B75FC4UL, 0x402DA172UL, 0x2FC9BAEEUL +); + +static int secp256k1_der_read_len(const unsigned char **sigp, const unsigned char *sigend) { + int lenleft, b1; + size_t ret = 0; + if (*sigp >= sigend) { + return -1; + } + b1 = *((*sigp)++); + if (b1 == 0xFF) { + /* X.690-0207 8.1.3.5.c the value 0xFF shall not be used. */ + return -1; + } + if ((b1 & 0x80) == 0) { + /* X.690-0207 8.1.3.4 short form length octets */ + return b1; + } + if (b1 == 0x80) { + /* Indefinite length is not allowed in DER. */ + return -1; + } + /* X.690-207 8.1.3.5 long form length octets */ + lenleft = b1 & 0x7F; + if (lenleft > sigend - *sigp) { + return -1; + } + if (**sigp == 0) { + /* Not the shortest possible length encoding. */ + return -1; + } + if ((size_t)lenleft > sizeof(size_t)) { + /* The resulting length would exceed the range of a size_t, so + * certainly longer than the passed array size. + */ + return -1; + } + while (lenleft > 0) { + if ((ret >> ((sizeof(size_t) - 1) * 8)) != 0) { + } + ret = (ret << 8) | **sigp; + if (ret + lenleft > (size_t)(sigend - *sigp)) { + /* Result exceeds the length of the passed array. */ + return -1; + } + (*sigp)++; + lenleft--; + } + if (ret < 128) { + /* Not the shortest possible length encoding. */ + return -1; + } + return ret; +} + +static int secp256k1_der_parse_integer(secp256k1_scalar *r, const unsigned char **sig, const unsigned char *sigend) { + int overflow = 0; + unsigned char ra[32] = {0}; + int rlen; + + if (*sig == sigend || **sig != 0x02) { + /* Not a primitive integer (X.690-0207 8.3.1). */ + return 0; + } + (*sig)++; + rlen = secp256k1_der_read_len(sig, sigend); + if (rlen <= 0 || (*sig) + rlen > sigend) { + /* Exceeds bounds or not at least length 1 (X.690-0207 8.3.1). */ + return 0; + } + if (**sig == 0x00 && rlen > 1 && (((*sig)[1]) & 0x80) == 0x00) { + /* Excessive 0x00 padding. */ + return 0; + } + if (**sig == 0xFF && rlen > 1 && (((*sig)[1]) & 0x80) == 0x80) { + /* Excessive 0xFF padding. */ + return 0; + } + if ((**sig & 0x80) == 0x80) { + /* Negative. */ + overflow = 1; + } + while (rlen > 0 && **sig == 0) { + /* Skip leading zero bytes */ + rlen--; + (*sig)++; + } + if (rlen > 32) { + overflow = 1; + } + if (!overflow) { + memcpy(ra + 32 - rlen, *sig, rlen); + secp256k1_scalar_set_b32(r, ra, &overflow); + } + if (overflow) { + secp256k1_scalar_set_int(r, 0); + } + (*sig) += rlen; + return 1; +} + +static int secp256k1_ecdsa_sig_parse(secp256k1_scalar *rr, secp256k1_scalar *rs, const unsigned char *sig, size_t size) { + const unsigned char *sigend = sig + size; + int rlen; + if (sig == sigend || *(sig++) != 0x30) { + /* The encoding doesn't start with a constructed sequence (X.690-0207 8.9.1). */ + return 0; + } + rlen = secp256k1_der_read_len(&sig, sigend); + if (rlen < 0 || sig + rlen > sigend) { + /* Tuple exceeds bounds */ + return 0; + } + if (sig + rlen != sigend) { + /* Garbage after tuple. */ + return 0; + } + + if (!secp256k1_der_parse_integer(rr, &sig, sigend)) { + return 0; + } + if (!secp256k1_der_parse_integer(rs, &sig, sigend)) { + return 0; + } + + if (sig != sigend) { + /* Trailing garbage inside tuple. */ + return 0; + } + + return 1; +} + +static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, size_t *size, const secp256k1_scalar* ar, const secp256k1_scalar* as) { + unsigned char r[33] = {0}, s[33] = {0}; + unsigned char *rp = r, *sp = s; + size_t lenR = 33, lenS = 33; + secp256k1_scalar_get_b32(&r[1], ar); + secp256k1_scalar_get_b32(&s[1], as); + while (lenR > 1 && rp[0] == 0 && rp[1] < 0x80) { lenR--; rp++; } + while (lenS > 1 && sp[0] == 0 && sp[1] < 0x80) { lenS--; sp++; } + if (*size < 6+lenS+lenR) { + *size = 6 + lenS + lenR; + return 0; + } + *size = 6 + lenS + lenR; + sig[0] = 0x30; + sig[1] = 4 + lenS + lenR; + sig[2] = 0x02; + sig[3] = lenR; + memcpy(sig+4, rp, lenR); + sig[4+lenR] = 0x02; + sig[5+lenR] = lenS; + memcpy(sig+lenR+6, sp, lenS); + return 1; +} + +static int secp256k1_ecdsa_sig_verify(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar *sigs, const secp256k1_ge *pubkey, const secp256k1_scalar *message) { + unsigned char c[32]; + secp256k1_scalar sn, u1, u2; +#if !defined(EXHAUSTIVE_TEST_ORDER) + secp256k1_fe xr; +#endif + secp256k1_gej pubkeyj; + secp256k1_gej pr; + + if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { + return 0; + } + + secp256k1_scalar_inverse_var(&sn, sigs); + secp256k1_scalar_mul(&u1, &sn, message); + secp256k1_scalar_mul(&u2, &sn, sigr); + secp256k1_gej_set_ge(&pubkeyj, pubkey); + secp256k1_ecmult(ctx, &pr, &pubkeyj, &u2, &u1); + if (secp256k1_gej_is_infinity(&pr)) { + return 0; + } + +#if defined(EXHAUSTIVE_TEST_ORDER) +{ + secp256k1_scalar computed_r; + secp256k1_ge pr_ge; + secp256k1_ge_set_gej(&pr_ge, &pr); + secp256k1_fe_normalize(&pr_ge.x); + + secp256k1_fe_get_b32(c, &pr_ge.x); + secp256k1_scalar_set_b32(&computed_r, c, NULL); + return secp256k1_scalar_eq(sigr, &computed_r); +} +#else + secp256k1_scalar_get_b32(c, sigr); + secp256k1_fe_set_b32(&xr, c); + + /** We now have the recomputed R point in pr, and its claimed x coordinate (modulo n) + * in xr. Naively, we would extract the x coordinate from pr (requiring a inversion modulo p), + * compute the remainder modulo n, and compare it to xr. However: + * + * xr == X(pr) mod n + * <=> exists h. (xr + h * n < p && xr + h * n == X(pr)) + * [Since 2 * n > p, h can only be 0 or 1] + * <=> (xr == X(pr)) || (xr + n < p && xr + n == X(pr)) + * [In Jacobian coordinates, X(pr) is pr.x / pr.z^2 mod p] + * <=> (xr == pr.x / pr.z^2 mod p) || (xr + n < p && xr + n == pr.x / pr.z^2 mod p) + * [Multiplying both sides of the equations by pr.z^2 mod p] + * <=> (xr * pr.z^2 mod p == pr.x) || (xr + n < p && (xr + n) * pr.z^2 mod p == pr.x) + * + * Thus, we can avoid the inversion, but we have to check both cases separately. + * secp256k1_gej_eq_x implements the (xr * pr.z^2 mod p == pr.x) test. + */ + if (secp256k1_gej_eq_x_var(&xr, &pr)) { + /* xr * pr.z^2 mod p == pr.x, so the signature is valid. */ + return 1; + } + if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_const_p_minus_order) >= 0) { + /* xr + n >= p, so we can skip testing the second case. */ + return 0; + } + secp256k1_fe_add(&xr, &secp256k1_ecdsa_const_order_as_fe); + if (secp256k1_gej_eq_x_var(&xr, &pr)) { + /* (xr + n) * pr.z^2 mod p == pr.x, so the signature is valid. */ + return 1; + } + return 0; +#endif +} + +static int secp256k1_ecdsa_sig_sign(const secp256k1_ecmult_gen_context *ctx, secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *seckey, const secp256k1_scalar *message, const secp256k1_scalar *nonce, int *recid) { + unsigned char b[32]; + secp256k1_gej rp; + secp256k1_ge r; + secp256k1_scalar n; + int overflow = 0; + + secp256k1_ecmult_gen(ctx, &rp, nonce); + secp256k1_ge_set_gej(&r, &rp); + secp256k1_fe_normalize(&r.x); + secp256k1_fe_normalize(&r.y); + secp256k1_fe_get_b32(b, &r.x); + secp256k1_scalar_set_b32(sigr, b, &overflow); + /* These two conditions should be checked before calling */ + VERIFY_CHECK(!secp256k1_scalar_is_zero(sigr)); + VERIFY_CHECK(overflow == 0); + + if (recid) { + /* The overflow condition is cryptographically unreachable as hitting it requires finding the discrete log + * of some P where P.x >= order, and only 1 in about 2^127 points meet this criteria. + */ + *recid = (overflow ? 2 : 0) | (secp256k1_fe_is_odd(&r.y) ? 1 : 0); + } + secp256k1_scalar_mul(&n, sigr, seckey); + secp256k1_scalar_add(&n, &n, message); + secp256k1_scalar_inverse(sigs, nonce); + secp256k1_scalar_mul(sigs, sigs, &n); + secp256k1_scalar_clear(&n); + secp256k1_gej_clear(&rp); + secp256k1_ge_clear(&r); + if (secp256k1_scalar_is_zero(sigs)) { + return 0; + } + if (secp256k1_scalar_is_high(sigs)) { + secp256k1_scalar_negate(sigs, sigs); + if (recid) { + *recid ^= 1; + } + } + return 1; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h new file mode 100644 index 00000000..42739a3b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey.h @@ -0,0 +1,25 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECKEY_ +#define _SECP256K1_ECKEY_ + +#include + +#include "group.h" +#include "scalar.h" +#include "ecmult.h" +#include "ecmult_gen.h" + +static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size); +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed); + +static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak); +static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); +static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak); +static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h new file mode 100644 index 00000000..ce38071a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/eckey_impl.h @@ -0,0 +1,99 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECKEY_IMPL_H_ +#define _SECP256K1_ECKEY_IMPL_H_ + +#include "eckey.h" + +#include "scalar.h" +#include "field.h" +#include "group.h" +#include "ecmult_gen.h" + +static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) { + if (size == 33 && (pub[0] == 0x02 || pub[0] == 0x03)) { + secp256k1_fe x; + return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == 0x03); + } else if (size == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07)) { + secp256k1_fe x, y; + if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) { + return 0; + } + secp256k1_ge_set_xy(elem, &x, &y); + if ((pub[0] == 0x06 || pub[0] == 0x07) && secp256k1_fe_is_odd(&y) != (pub[0] == 0x07)) { + return 0; + } + return secp256k1_ge_is_valid_var(elem); + } else { + return 0; + } +} + +static int secp256k1_eckey_pubkey_serialize(secp256k1_ge *elem, unsigned char *pub, size_t *size, int compressed) { + if (secp256k1_ge_is_infinity(elem)) { + return 0; + } + secp256k1_fe_normalize_var(&elem->x); + secp256k1_fe_normalize_var(&elem->y); + secp256k1_fe_get_b32(&pub[1], &elem->x); + if (compressed) { + *size = 33; + pub[0] = 0x02 | (secp256k1_fe_is_odd(&elem->y) ? 0x01 : 0x00); + } else { + *size = 65; + pub[0] = 0x04; + secp256k1_fe_get_b32(&pub[33], &elem->y); + } + return 1; +} + +static int secp256k1_eckey_privkey_tweak_add(secp256k1_scalar *key, const secp256k1_scalar *tweak) { + secp256k1_scalar_add(key, key, tweak); + if (secp256k1_scalar_is_zero(key)) { + return 0; + } + return 1; +} + +static int secp256k1_eckey_pubkey_tweak_add(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { + secp256k1_gej pt; + secp256k1_scalar one; + secp256k1_gej_set_ge(&pt, key); + secp256k1_scalar_set_int(&one, 1); + secp256k1_ecmult(ctx, &pt, &pt, &one, tweak); + + if (secp256k1_gej_is_infinity(&pt)) { + return 0; + } + secp256k1_ge_set_gej(key, &pt); + return 1; +} + +static int secp256k1_eckey_privkey_tweak_mul(secp256k1_scalar *key, const secp256k1_scalar *tweak) { + if (secp256k1_scalar_is_zero(tweak)) { + return 0; + } + + secp256k1_scalar_mul(key, key, tweak); + return 1; +} + +static int secp256k1_eckey_pubkey_tweak_mul(const secp256k1_ecmult_context *ctx, secp256k1_ge *key, const secp256k1_scalar *tweak) { + secp256k1_scalar zero; + secp256k1_gej pt; + if (secp256k1_scalar_is_zero(tweak)) { + return 0; + } + + secp256k1_scalar_set_int(&zero, 0); + secp256k1_gej_set_ge(&pt, key); + secp256k1_ecmult(ctx, &pt, &pt, tweak, &zero); + secp256k1_ge_set_gej(key, &pt); + return 1; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h new file mode 100644 index 00000000..20484134 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult.h @@ -0,0 +1,31 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_ +#define _SECP256K1_ECMULT_ + +#include "num.h" +#include "group.h" + +typedef struct { + /* For accelerating the computation of a*P + b*G: */ + secp256k1_ge_storage (*pre_g)[]; /* odd multiples of the generator */ +#ifdef USE_ENDOMORPHISM + secp256k1_ge_storage (*pre_g_128)[]; /* odd multiples of 2^128*generator */ +#endif +} secp256k1_ecmult_context; + +static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx); +static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb); +static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, + const secp256k1_ecmult_context *src, const secp256k1_callback *cb); +static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx); +static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx); + +/** Double multiply: R = na*A + ng*G */ +static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h new file mode 100644 index 00000000..2b009765 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const.h @@ -0,0 +1,15 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_CONST_ +#define _SECP256K1_ECMULT_CONST_ + +#include "scalar.h" +#include "group.h" + +static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h new file mode 100644 index 00000000..0db314c4 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_const_impl.h @@ -0,0 +1,239 @@ +/********************************************************************** + * Copyright (c) 2015 Pieter Wuille, Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_CONST_IMPL_ +#define _SECP256K1_ECMULT_CONST_IMPL_ + +#include "scalar.h" +#include "group.h" +#include "ecmult_const.h" +#include "ecmult_impl.h" + +#ifdef USE_ENDOMORPHISM + #define WNAF_BITS 128 +#else + #define WNAF_BITS 256 +#endif +#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w)) + +/* This is like `ECMULT_TABLE_GET_GE` but is constant time */ +#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \ + int m; \ + int abs_n = (n) * (((n) > 0) * 2 - 1); \ + int idx_n = abs_n / 2; \ + secp256k1_fe neg_y; \ + VERIFY_CHECK(((n) & 1) == 1); \ + VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ + VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ + VERIFY_SETUP(secp256k1_fe_clear(&(r)->x)); \ + VERIFY_SETUP(secp256k1_fe_clear(&(r)->y)); \ + for (m = 0; m < ECMULT_TABLE_SIZE(w); m++) { \ + /* This loop is used to avoid secret data in array indices. See + * the comment in ecmult_gen_impl.h for rationale. */ \ + secp256k1_fe_cmov(&(r)->x, &(pre)[m].x, m == idx_n); \ + secp256k1_fe_cmov(&(r)->y, &(pre)[m].y, m == idx_n); \ + } \ + (r)->infinity = 0; \ + secp256k1_fe_negate(&neg_y, &(r)->y, 1); \ + secp256k1_fe_cmov(&(r)->y, &neg_y, (n) != abs_n); \ +} while(0) + + +/** Convert a number to WNAF notation. The number becomes represented by sum(2^{wi} * wnaf[i], i=0..return_val) + * with the following guarantees: + * - each wnaf[i] an odd integer between -(1 << w) and (1 << w) + * - each wnaf[i] is nonzero + * - the number of words set is returned; this is always (WNAF_BITS + w - 1) / w + * + * Adapted from `The Width-w NAF Method Provides Small Memory and Fast Elliptic Scalar + * Multiplications Secure against Side Channel Attacks`, Okeya and Tagaki. M. Joye (Ed.) + * CT-RSA 2003, LNCS 2612, pp. 328-443, 2003. Springer-Verlagy Berlin Heidelberg 2003 + * + * Numbers reference steps of `Algorithm SPA-resistant Width-w NAF with Odd Scalar` on pp. 335 + */ +static int secp256k1_wnaf_const(int *wnaf, secp256k1_scalar s, int w) { + int global_sign; + int skew = 0; + int word = 0; + + /* 1 2 3 */ + int u_last; + int u; + + int flip; + int bit; + secp256k1_scalar neg_s; + int not_neg_one; + /* Note that we cannot handle even numbers by negating them to be odd, as is + * done in other implementations, since if our scalars were specified to have + * width < 256 for performance reasons, their negations would have width 256 + * and we'd lose any performance benefit. Instead, we use a technique from + * Section 4.2 of the Okeya/Tagaki paper, which is to add either 1 (for even) + * or 2 (for odd) to the number we are encoding, returning a skew value indicating + * this, and having the caller compensate after doing the multiplication. */ + + /* Negative numbers will be negated to keep their bit representation below the maximum width */ + flip = secp256k1_scalar_is_high(&s); + /* We add 1 to even numbers, 2 to odd ones, noting that negation flips parity */ + bit = flip ^ !secp256k1_scalar_is_even(&s); + /* We check for negative one, since adding 2 to it will cause an overflow */ + secp256k1_scalar_negate(&neg_s, &s); + not_neg_one = !secp256k1_scalar_is_one(&neg_s); + secp256k1_scalar_cadd_bit(&s, bit, not_neg_one); + /* If we had negative one, flip == 1, s.d[0] == 0, bit == 1, so caller expects + * that we added two to it and flipped it. In fact for -1 these operations are + * identical. We only flipped, but since skewing is required (in the sense that + * the skew must be 1 or 2, never zero) and flipping is not, we need to change + * our flags to claim that we only skewed. */ + global_sign = secp256k1_scalar_cond_negate(&s, flip); + global_sign *= not_neg_one * 2 - 1; + skew = 1 << bit; + + /* 4 */ + u_last = secp256k1_scalar_shr_int(&s, w); + while (word * w < WNAF_BITS) { + int sign; + int even; + + /* 4.1 4.4 */ + u = secp256k1_scalar_shr_int(&s, w); + /* 4.2 */ + even = ((u & 1) == 0); + sign = 2 * (u_last > 0) - 1; + u += sign * even; + u_last -= sign * even * (1 << w); + + /* 4.3, adapted for global sign change */ + wnaf[word++] = u_last * global_sign; + + u_last = u; + } + wnaf[word] = u * global_sign; + + VERIFY_CHECK(secp256k1_scalar_is_zero(&s)); + VERIFY_CHECK(word == WNAF_SIZE(w)); + return skew; +} + + +static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) { + secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_ge tmpa; + secp256k1_fe Z; + + int skew_1; + int wnaf_1[1 + WNAF_SIZE(WINDOW_A - 1)]; +#ifdef USE_ENDOMORPHISM + secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; + int wnaf_lam[1 + WNAF_SIZE(WINDOW_A - 1)]; + int skew_lam; + secp256k1_scalar q_1, q_lam; +#endif + + int i; + secp256k1_scalar sc = *scalar; + + /* build wnaf representation for q. */ +#ifdef USE_ENDOMORPHISM + /* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */ + secp256k1_scalar_split_lambda(&q_1, &q_lam, &sc); + skew_1 = secp256k1_wnaf_const(wnaf_1, q_1, WINDOW_A - 1); + skew_lam = secp256k1_wnaf_const(wnaf_lam, q_lam, WINDOW_A - 1); +#else + skew_1 = secp256k1_wnaf_const(wnaf_1, sc, WINDOW_A - 1); +#endif + + /* Calculate odd multiples of a. + * All multiples are brought to the same Z 'denominator', which is stored + * in Z. Due to secp256k1' isomorphism we can do all operations pretending + * that the Z coordinate was 1, use affine addition formulae, and correct + * the Z coordinate of the result once at the end. + */ + secp256k1_gej_set_ge(r, a); + secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, r); + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_fe_normalize_weak(&pre_a[i].y); + } +#ifdef USE_ENDOMORPHISM + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + } +#endif + + /* first loop iteration (separated out so we can directly set r, rather + * than having it start at infinity, get doubled several times, then have + * its new value added to it) */ + i = wnaf_1[WNAF_SIZE(WINDOW_A - 1)]; + VERIFY_CHECK(i != 0); + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A); + secp256k1_gej_set_ge(r, &tmpa); +#ifdef USE_ENDOMORPHISM + i = wnaf_lam[WNAF_SIZE(WINDOW_A - 1)]; + VERIFY_CHECK(i != 0); + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A); + secp256k1_gej_add_ge(r, r, &tmpa); +#endif + /* remaining loop iterations */ + for (i = WNAF_SIZE(WINDOW_A - 1) - 1; i >= 0; i--) { + int n; + int j; + for (j = 0; j < WINDOW_A - 1; ++j) { + secp256k1_gej_double_nonzero(r, r, NULL); + } + + n = wnaf_1[i]; + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + VERIFY_CHECK(n != 0); + secp256k1_gej_add_ge(r, r, &tmpa); +#ifdef USE_ENDOMORPHISM + n = wnaf_lam[i]; + ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); + VERIFY_CHECK(n != 0); + secp256k1_gej_add_ge(r, r, &tmpa); +#endif + } + + secp256k1_fe_mul(&r->z, &r->z, &Z); + + { + /* Correct for wNAF skew */ + secp256k1_ge correction = *a; + secp256k1_ge_storage correction_1_stor; +#ifdef USE_ENDOMORPHISM + secp256k1_ge_storage correction_lam_stor; +#endif + secp256k1_ge_storage a2_stor; + secp256k1_gej tmpj; + secp256k1_gej_set_ge(&tmpj, &correction); + secp256k1_gej_double_var(&tmpj, &tmpj, NULL); + secp256k1_ge_set_gej(&correction, &tmpj); + secp256k1_ge_to_storage(&correction_1_stor, a); +#ifdef USE_ENDOMORPHISM + secp256k1_ge_to_storage(&correction_lam_stor, a); +#endif + secp256k1_ge_to_storage(&a2_stor, &correction); + + /* For odd numbers this is 2a (so replace it), for even ones a (so no-op) */ + secp256k1_ge_storage_cmov(&correction_1_stor, &a2_stor, skew_1 == 2); +#ifdef USE_ENDOMORPHISM + secp256k1_ge_storage_cmov(&correction_lam_stor, &a2_stor, skew_lam == 2); +#endif + + /* Apply the correction */ + secp256k1_ge_from_storage(&correction, &correction_1_stor); + secp256k1_ge_neg(&correction, &correction); + secp256k1_gej_add_ge(r, r, &correction); + +#ifdef USE_ENDOMORPHISM + secp256k1_ge_from_storage(&correction, &correction_lam_stor); + secp256k1_ge_neg(&correction, &correction); + secp256k1_ge_mul_lambda(&correction, &correction); + secp256k1_gej_add_ge(r, r, &correction); +#endif + } +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h new file mode 100644 index 00000000..eb2cc9ea --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen.h @@ -0,0 +1,43 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_GEN_ +#define _SECP256K1_ECMULT_GEN_ + +#include "scalar.h" +#include "group.h" + +typedef struct { + /* For accelerating the computation of a*G: + * To harden against timing attacks, use the following mechanism: + * * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. + * * Compute sum(n_i * 16^i * G + U_i, i=0..63), where: + * * U_i = U * 2^i (for i=0..62) + * * U_i = U * (1-2^63) (for i=63) + * where U is a point with no known corresponding scalar. Note that sum(U_i, i=0..63) = 0. + * For each i, and each of the 16 possible values of n_i, (n_i * 16^i * G + U_i) is + * precomputed (call it prec(i, n_i)). The formula now becomes sum(prec(i, n_i), i=0..63). + * None of the resulting prec group elements have a known scalar, and neither do any of + * the intermediate sums while computing a*G. + */ + secp256k1_ge_storage (*prec)[64][16]; /* prec[j][i] = 16^j * i * G + U_i */ + secp256k1_scalar blind; + secp256k1_gej initial; +} secp256k1_ecmult_gen_context; + +static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context* ctx); +static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context* ctx, const secp256k1_callback* cb); +static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, + const secp256k1_ecmult_gen_context* src, const secp256k1_callback* cb); +static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context* ctx); +static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx); + +/** Multiply with the generator: R = a*G */ +static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context* ctx, secp256k1_gej *r, const secp256k1_scalar *a); + +static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h new file mode 100644 index 00000000..35f25460 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_gen_impl.h @@ -0,0 +1,210 @@ +/********************************************************************** + * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_GEN_IMPL_H_ +#define _SECP256K1_ECMULT_GEN_IMPL_H_ + +#include "scalar.h" +#include "group.h" +#include "ecmult_gen.h" +#include "hash_impl.h" +#ifdef USE_ECMULT_STATIC_PRECOMPUTATION +#include "ecmult_static_context.h" +#endif +static void secp256k1_ecmult_gen_context_init(secp256k1_ecmult_gen_context *ctx) { + ctx->prec = NULL; +} + +static void secp256k1_ecmult_gen_context_build(secp256k1_ecmult_gen_context *ctx, const secp256k1_callback* cb) { +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + secp256k1_ge prec[1024]; + secp256k1_gej gj; + secp256k1_gej nums_gej; + int i, j; +#endif + + if (ctx->prec != NULL) { + return; + } +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + ctx->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*ctx->prec)); + + /* get the generator */ + secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); + + /* Construct a group element with no known corresponding scalar (nothing up my sleeve). */ + { + static const unsigned char nums_b32[33] = "The scalar for this x is unknown"; + secp256k1_fe nums_x; + secp256k1_ge nums_ge; + int r; + r = secp256k1_fe_set_b32(&nums_x, nums_b32); + (void)r; + VERIFY_CHECK(r); + r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0); + (void)r; + VERIFY_CHECK(r); + secp256k1_gej_set_ge(&nums_gej, &nums_ge); + /* Add G to make the bits in x uniformly distributed. */ + secp256k1_gej_add_ge_var(&nums_gej, &nums_gej, &secp256k1_ge_const_g, NULL); + } + + /* compute prec. */ + { + secp256k1_gej precj[1024]; /* Jacobian versions of prec. */ + secp256k1_gej gbase; + secp256k1_gej numsbase; + gbase = gj; /* 16^j * G */ + numsbase = nums_gej; /* 2^j * nums. */ + for (j = 0; j < 64; j++) { + /* Set precj[j*16 .. j*16+15] to (numsbase, numsbase + gbase, ..., numsbase + 15*gbase). */ + precj[j*16] = numsbase; + for (i = 1; i < 16; i++) { + secp256k1_gej_add_var(&precj[j*16 + i], &precj[j*16 + i - 1], &gbase, NULL); + } + /* Multiply gbase by 16. */ + for (i = 0; i < 4; i++) { + secp256k1_gej_double_var(&gbase, &gbase, NULL); + } + /* Multiply numbase by 2. */ + secp256k1_gej_double_var(&numsbase, &numsbase, NULL); + if (j == 62) { + /* In the last iteration, numsbase is (1 - 2^j) * nums instead. */ + secp256k1_gej_neg(&numsbase, &numsbase); + secp256k1_gej_add_var(&numsbase, &numsbase, &nums_gej, NULL); + } + } + secp256k1_ge_set_all_gej_var(prec, precj, 1024, cb); + } + for (j = 0; j < 64; j++) { + for (i = 0; i < 16; i++) { + secp256k1_ge_to_storage(&(*ctx->prec)[j][i], &prec[j*16 + i]); + } + } +#else + (void)cb; + ctx->prec = (secp256k1_ge_storage (*)[64][16])secp256k1_ecmult_static_context; +#endif + secp256k1_ecmult_gen_blind(ctx, NULL); +} + +static int secp256k1_ecmult_gen_context_is_built(const secp256k1_ecmult_gen_context* ctx) { + return ctx->prec != NULL; +} + +static void secp256k1_ecmult_gen_context_clone(secp256k1_ecmult_gen_context *dst, + const secp256k1_ecmult_gen_context *src, const secp256k1_callback* cb) { + if (src->prec == NULL) { + dst->prec = NULL; + } else { +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + dst->prec = (secp256k1_ge_storage (*)[64][16])checked_malloc(cb, sizeof(*dst->prec)); + memcpy(dst->prec, src->prec, sizeof(*dst->prec)); +#else + (void)cb; + dst->prec = src->prec; +#endif + dst->initial = src->initial; + dst->blind = src->blind; + } +} + +static void secp256k1_ecmult_gen_context_clear(secp256k1_ecmult_gen_context *ctx) { +#ifndef USE_ECMULT_STATIC_PRECOMPUTATION + free(ctx->prec); +#endif + secp256k1_scalar_clear(&ctx->blind); + secp256k1_gej_clear(&ctx->initial); + ctx->prec = NULL; +} + +static void secp256k1_ecmult_gen(const secp256k1_ecmult_gen_context *ctx, secp256k1_gej *r, const secp256k1_scalar *gn) { + secp256k1_ge add; + secp256k1_ge_storage adds; + secp256k1_scalar gnb; + int bits; + int i, j; + memset(&adds, 0, sizeof(adds)); + *r = ctx->initial; + /* Blind scalar/point multiplication by computing (n-b)G + bG instead of nG. */ + secp256k1_scalar_add(&gnb, gn, &ctx->blind); + add.infinity = 0; + for (j = 0; j < 64; j++) { + bits = secp256k1_scalar_get_bits(&gnb, j * 4, 4); + for (i = 0; i < 16; i++) { + /** This uses a conditional move to avoid any secret data in array indexes. + * _Any_ use of secret indexes has been demonstrated to result in timing + * sidechannels, even when the cache-line access patterns are uniform. + * See also: + * "A word of warning", CHES 2013 Rump Session, by Daniel J. Bernstein and Peter Schwabe + * (https://cryptojedi.org/peter/data/chesrump-20130822.pdf) and + * "Cache Attacks and Countermeasures: the Case of AES", RSA 2006, + * by Dag Arne Osvik, Adi Shamir, and Eran Tromer + * (http://www.tau.ac.il/~tromer/papers/cache.pdf) + */ + secp256k1_ge_storage_cmov(&adds, &(*ctx->prec)[j][i], i == bits); + } + secp256k1_ge_from_storage(&add, &adds); + secp256k1_gej_add_ge(r, r, &add); + } + bits = 0; + secp256k1_ge_clear(&add); + secp256k1_scalar_clear(&gnb); +} + +/* Setup blinding values for secp256k1_ecmult_gen. */ +static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const unsigned char *seed32) { + secp256k1_scalar b; + secp256k1_gej gb; + secp256k1_fe s; + unsigned char nonce32[32]; + secp256k1_rfc6979_hmac_sha256_t rng; + int retry; + unsigned char keydata[64] = {0}; + if (seed32 == NULL) { + /* When seed is NULL, reset the initial point and blinding value. */ + secp256k1_gej_set_ge(&ctx->initial, &secp256k1_ge_const_g); + secp256k1_gej_neg(&ctx->initial, &ctx->initial); + secp256k1_scalar_set_int(&ctx->blind, 1); + } + /* The prior blinding value (if not reset) is chained forward by including it in the hash. */ + secp256k1_scalar_get_b32(nonce32, &ctx->blind); + /** Using a CSPRNG allows a failure free interface, avoids needing large amounts of random data, + * and guards against weak or adversarial seeds. This is a simpler and safer interface than + * asking the caller for blinding values directly and expecting them to retry on failure. + */ + memcpy(keydata, nonce32, 32); + if (seed32 != NULL) { + memcpy(keydata + 32, seed32, 32); + } + secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, seed32 ? 64 : 32); + memset(keydata, 0, sizeof(keydata)); + /* Retry for out of range results to achieve uniformity. */ + do { + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + retry = !secp256k1_fe_set_b32(&s, nonce32); + retry |= secp256k1_fe_is_zero(&s); + } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > Fp. */ + /* Randomize the projection to defend against multiplier sidechannels. */ + secp256k1_gej_rescale(&ctx->initial, &s); + secp256k1_fe_clear(&s); + do { + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + secp256k1_scalar_set_b32(&b, nonce32, &retry); + /* A blinding value of 0 works, but would undermine the projection hardening. */ + retry |= secp256k1_scalar_is_zero(&b); + } while (retry); /* This branch true is cryptographically unreachable. Requires sha256_hmac output > order. */ + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + memset(nonce32, 0, 32); + secp256k1_ecmult_gen(ctx, &gb, &b); + secp256k1_scalar_negate(&b, &b); + ctx->blind = b; + ctx->initial = gb; + secp256k1_scalar_clear(&b); + secp256k1_gej_clear(&gb); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h new file mode 100644 index 00000000..4e40104a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/ecmult_impl.h @@ -0,0 +1,406 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_ECMULT_IMPL_H_ +#define _SECP256K1_ECMULT_IMPL_H_ + +#include + +#include "group.h" +#include "scalar.h" +#include "ecmult.h" + +#if defined(EXHAUSTIVE_TEST_ORDER) +/* We need to lower these values for exhaustive tests because + * the tables cannot have infinities in them (this breaks the + * affine-isomorphism stuff which tracks z-ratios) */ +# if EXHAUSTIVE_TEST_ORDER > 128 +# define WINDOW_A 5 +# define WINDOW_G 8 +# elif EXHAUSTIVE_TEST_ORDER > 8 +# define WINDOW_A 4 +# define WINDOW_G 4 +# else +# define WINDOW_A 2 +# define WINDOW_G 2 +# endif +#else +/* optimal for 128-bit and 256-bit exponents. */ +#define WINDOW_A 5 +/** larger numbers may result in slightly better performance, at the cost of + exponentially larger precomputed tables. */ +#ifdef USE_ENDOMORPHISM +/** Two tables for window size 15: 1.375 MiB. */ +#define WINDOW_G 15 +#else +/** One table for window size 16: 1.375 MiB. */ +#define WINDOW_G 16 +#endif +#endif + +/** The number of entries a table with precomputed multiples needs to have. */ +#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) + +/** Fill a table 'prej' with precomputed odd multiples of a. Prej will contain + * the values [1*a,3*a,...,(2*n-1)*a], so it space for n values. zr[0] will + * contain prej[0].z / a.z. The other zr[i] values = prej[i].z / prej[i-1].z. + * Prej's Z values are undefined, except for the last value. + */ +static void secp256k1_ecmult_odd_multiples_table(int n, secp256k1_gej *prej, secp256k1_fe *zr, const secp256k1_gej *a) { + secp256k1_gej d; + secp256k1_ge a_ge, d_ge; + int i; + + VERIFY_CHECK(!a->infinity); + + secp256k1_gej_double_var(&d, a, NULL); + + /* + * Perform the additions on an isomorphism where 'd' is affine: drop the z coordinate + * of 'd', and scale the 1P starting value's x/y coordinates without changing its z. + */ + d_ge.x = d.x; + d_ge.y = d.y; + d_ge.infinity = 0; + + secp256k1_ge_set_gej_zinv(&a_ge, a, &d.z); + prej[0].x = a_ge.x; + prej[0].y = a_ge.y; + prej[0].z = a->z; + prej[0].infinity = 0; + + zr[0] = d.z; + for (i = 1; i < n; i++) { + secp256k1_gej_add_ge_var(&prej[i], &prej[i-1], &d_ge, &zr[i]); + } + + /* + * Each point in 'prej' has a z coordinate too small by a factor of 'd.z'. Only + * the final point's z coordinate is actually used though, so just update that. + */ + secp256k1_fe_mul(&prej[n-1].z, &prej[n-1].z, &d.z); +} + +/** Fill a table 'pre' with precomputed odd multiples of a. + * + * There are two versions of this function: + * - secp256k1_ecmult_odd_multiples_table_globalz_windowa which brings its + * resulting point set to a single constant Z denominator, stores the X and Y + * coordinates as ge_storage points in pre, and stores the global Z in rz. + * It only operates on tables sized for WINDOW_A wnaf multiples. + * - secp256k1_ecmult_odd_multiples_table_storage_var, which converts its + * resulting point set to actually affine points, and stores those in pre. + * It operates on tables of any size, but uses heap-allocated temporaries. + * + * To compute a*P + b*G, we compute a table for P using the first function, + * and for G using the second (which requires an inverse, but it only needs to + * happen once). + */ +static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *pre, secp256k1_fe *globalz, const secp256k1_gej *a) { + secp256k1_gej prej[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_fe zr[ECMULT_TABLE_SIZE(WINDOW_A)]; + + /* Compute the odd multiples in Jacobian form. */ + secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), prej, zr, a); + /* Bring them to the same Z denominator. */ + secp256k1_ge_globalz_set_table_gej(ECMULT_TABLE_SIZE(WINDOW_A), pre, globalz, prej, zr); +} + +static void secp256k1_ecmult_odd_multiples_table_storage_var(int n, secp256k1_ge_storage *pre, const secp256k1_gej *a, const secp256k1_callback *cb) { + secp256k1_gej *prej = (secp256k1_gej*)checked_malloc(cb, sizeof(secp256k1_gej) * n); + secp256k1_ge *prea = (secp256k1_ge*)checked_malloc(cb, sizeof(secp256k1_ge) * n); + secp256k1_fe *zr = (secp256k1_fe*)checked_malloc(cb, sizeof(secp256k1_fe) * n); + int i; + + /* Compute the odd multiples in Jacobian form. */ + secp256k1_ecmult_odd_multiples_table(n, prej, zr, a); + /* Convert them in batch to affine coordinates. */ + secp256k1_ge_set_table_gej_var(prea, prej, zr, n); + /* Convert them to compact storage form. */ + for (i = 0; i < n; i++) { + secp256k1_ge_to_storage(&pre[i], &prea[i]); + } + + free(prea); + free(prej); + free(zr); +} + +/** The following two macro retrieves a particular odd multiple from a table + * of precomputed multiples. */ +#define ECMULT_TABLE_GET_GE(r,pre,n,w) do { \ + VERIFY_CHECK(((n) & 1) == 1); \ + VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ + VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ + if ((n) > 0) { \ + *(r) = (pre)[((n)-1)/2]; \ + } else { \ + secp256k1_ge_neg((r), &(pre)[(-(n)-1)/2]); \ + } \ +} while(0) + +#define ECMULT_TABLE_GET_GE_STORAGE(r,pre,n,w) do { \ + VERIFY_CHECK(((n) & 1) == 1); \ + VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ + VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ + if ((n) > 0) { \ + secp256k1_ge_from_storage((r), &(pre)[((n)-1)/2]); \ + } else { \ + secp256k1_ge_from_storage((r), &(pre)[(-(n)-1)/2]); \ + secp256k1_ge_neg((r), (r)); \ + } \ +} while(0) + +static void secp256k1_ecmult_context_init(secp256k1_ecmult_context *ctx) { + ctx->pre_g = NULL; +#ifdef USE_ENDOMORPHISM + ctx->pre_g_128 = NULL; +#endif +} + +static void secp256k1_ecmult_context_build(secp256k1_ecmult_context *ctx, const secp256k1_callback *cb) { + secp256k1_gej gj; + + if (ctx->pre_g != NULL) { + return; + } + + /* get the generator */ + secp256k1_gej_set_ge(&gj, &secp256k1_ge_const_g); + + ctx->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); + + /* precompute the tables with odd multiples */ + secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g, &gj, cb); + +#ifdef USE_ENDOMORPHISM + { + secp256k1_gej g_128j; + int i; + + ctx->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, sizeof((*ctx->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G)); + + /* calculate 2^128*generator */ + g_128j = gj; + for (i = 0; i < 128; i++) { + secp256k1_gej_double_var(&g_128j, &g_128j, NULL); + } + secp256k1_ecmult_odd_multiples_table_storage_var(ECMULT_TABLE_SIZE(WINDOW_G), *ctx->pre_g_128, &g_128j, cb); + } +#endif +} + +static void secp256k1_ecmult_context_clone(secp256k1_ecmult_context *dst, + const secp256k1_ecmult_context *src, const secp256k1_callback *cb) { + if (src->pre_g == NULL) { + dst->pre_g = NULL; + } else { + size_t size = sizeof((*dst->pre_g)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); + dst->pre_g = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); + memcpy(dst->pre_g, src->pre_g, size); + } +#ifdef USE_ENDOMORPHISM + if (src->pre_g_128 == NULL) { + dst->pre_g_128 = NULL; + } else { + size_t size = sizeof((*dst->pre_g_128)[0]) * ECMULT_TABLE_SIZE(WINDOW_G); + dst->pre_g_128 = (secp256k1_ge_storage (*)[])checked_malloc(cb, size); + memcpy(dst->pre_g_128, src->pre_g_128, size); + } +#endif +} + +static int secp256k1_ecmult_context_is_built(const secp256k1_ecmult_context *ctx) { + return ctx->pre_g != NULL; +} + +static void secp256k1_ecmult_context_clear(secp256k1_ecmult_context *ctx) { + free(ctx->pre_g); +#ifdef USE_ENDOMORPHISM + free(ctx->pre_g_128); +#endif + secp256k1_ecmult_context_init(ctx); +} + +/** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), + * with the following guarantees: + * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) + * - two non-zero entries in wnaf are separated by at least w-1 zeroes. + * - the number of set values in wnaf is returned. This number is at most 256, and at most one more + * than the number of bits in the (absolute value) of the input. + */ +static int secp256k1_ecmult_wnaf(int *wnaf, int len, const secp256k1_scalar *a, int w) { + secp256k1_scalar s = *a; + int last_set_bit = -1; + int bit = 0; + int sign = 1; + int carry = 0; + + VERIFY_CHECK(wnaf != NULL); + VERIFY_CHECK(0 <= len && len <= 256); + VERIFY_CHECK(a != NULL); + VERIFY_CHECK(2 <= w && w <= 31); + + memset(wnaf, 0, len * sizeof(wnaf[0])); + + if (secp256k1_scalar_get_bits(&s, 255, 1)) { + secp256k1_scalar_negate(&s, &s); + sign = -1; + } + + while (bit < len) { + int now; + int word; + if (secp256k1_scalar_get_bits(&s, bit, 1) == (unsigned int)carry) { + bit++; + continue; + } + + now = w; + if (now > len - bit) { + now = len - bit; + } + + word = secp256k1_scalar_get_bits_var(&s, bit, now) + carry; + + carry = (word >> (w-1)) & 1; + word -= carry << w; + + wnaf[bit] = sign * word; + last_set_bit = bit; + + bit += now; + } +#ifdef VERIFY + CHECK(carry == 0); + while (bit < 256) { + CHECK(secp256k1_scalar_get_bits(&s, bit++, 1) == 0); + } +#endif + return last_set_bit + 1; +} + +static void secp256k1_ecmult(const secp256k1_ecmult_context *ctx, secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_scalar *na, const secp256k1_scalar *ng) { + secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_ge tmpa; + secp256k1_fe Z; +#ifdef USE_ENDOMORPHISM + secp256k1_ge pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; + secp256k1_scalar na_1, na_lam; + /* Splitted G factors. */ + secp256k1_scalar ng_1, ng_128; + int wnaf_na_1[130]; + int wnaf_na_lam[130]; + int bits_na_1; + int bits_na_lam; + int wnaf_ng_1[129]; + int bits_ng_1; + int wnaf_ng_128[129]; + int bits_ng_128; +#else + int wnaf_na[256]; + int bits_na; + int wnaf_ng[256]; + int bits_ng; +#endif + int i; + int bits; + +#ifdef USE_ENDOMORPHISM + /* split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) */ + secp256k1_scalar_split_lambda(&na_1, &na_lam, na); + + /* build wnaf representation for na_1 and na_lam. */ + bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, 130, &na_1, WINDOW_A); + bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, 130, &na_lam, WINDOW_A); + VERIFY_CHECK(bits_na_1 <= 130); + VERIFY_CHECK(bits_na_lam <= 130); + bits = bits_na_1; + if (bits_na_lam > bits) { + bits = bits_na_lam; + } +#else + /* build wnaf representation for na. */ + bits_na = secp256k1_ecmult_wnaf(wnaf_na, 256, na, WINDOW_A); + bits = bits_na; +#endif + + /* Calculate odd multiples of a. + * All multiples are brought to the same Z 'denominator', which is stored + * in Z. Due to secp256k1' isomorphism we can do all operations pretending + * that the Z coordinate was 1, use affine addition formulae, and correct + * the Z coordinate of the result once at the end. + * The exception is the precomputed G table points, which are actually + * affine. Compared to the base used for other points, they have a Z ratio + * of 1/Z, so we can use secp256k1_gej_add_zinv_var, which uses the same + * isomorphism to efficiently add with a known Z inverse. + */ + secp256k1_ecmult_odd_multiples_table_globalz_windowa(pre_a, &Z, a); + +#ifdef USE_ENDOMORPHISM + for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) { + secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]); + } + + /* split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) */ + secp256k1_scalar_split_128(&ng_1, &ng_128, ng); + + /* Build wnaf representation for ng_1 and ng_128 */ + bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, 129, &ng_1, WINDOW_G); + bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, 129, &ng_128, WINDOW_G); + if (bits_ng_1 > bits) { + bits = bits_ng_1; + } + if (bits_ng_128 > bits) { + bits = bits_ng_128; + } +#else + bits_ng = secp256k1_ecmult_wnaf(wnaf_ng, 256, ng, WINDOW_G); + if (bits_ng > bits) { + bits = bits_ng; + } +#endif + + secp256k1_gej_set_infinity(r); + + for (i = bits - 1; i >= 0; i--) { + int n; + secp256k1_gej_double_var(r, r, NULL); +#ifdef USE_ENDOMORPHISM + if (i < bits_na_1 && (n = wnaf_na_1[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } + if (i < bits_na_lam && (n = wnaf_na_lam[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } + if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { + ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); + secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); + } + if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { + ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g_128, n, WINDOW_G); + secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); + } +#else + if (i < bits_na && (n = wnaf_na[i])) { + ECMULT_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A); + secp256k1_gej_add_ge_var(r, r, &tmpa, NULL); + } + if (i < bits_ng && (n = wnaf_ng[i])) { + ECMULT_TABLE_GET_GE_STORAGE(&tmpa, *ctx->pre_g, n, WINDOW_G); + secp256k1_gej_add_zinv_var(r, r, &tmpa, &Z); + } +#endif + } + + if (!r->infinity) { + secp256k1_fe_mul(&r->z, &r->z, &Z); + } +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h new file mode 100644 index 00000000..bbb1ee86 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field.h @@ -0,0 +1,132 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_ +#define _SECP256K1_FIELD_ + +/** Field element module. + * + * Field elements can be represented in several ways, but code accessing + * it (and implementations) need to take certain properties into account: + * - Each field element can be normalized or not. + * - Each field element has a magnitude, which represents how far away + * its representation is away from normalization. Normalized elements + * always have a magnitude of 1, but a magnitude of 1 doesn't imply + * normality. + */ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(USE_FIELD_10X26) +#include "field_10x26.h" +#elif defined(USE_FIELD_5X52) +#include "field_5x52.h" +#else +#error "Please select field implementation" +#endif + +#include "util.h" + +/** Normalize a field element. */ +static void secp256k1_fe_normalize(secp256k1_fe *r); + +/** Weakly normalize a field element: reduce it magnitude to 1, but don't fully normalize. */ +static void secp256k1_fe_normalize_weak(secp256k1_fe *r); + +/** Normalize a field element, without constant-time guarantee. */ +static void secp256k1_fe_normalize_var(secp256k1_fe *r); + +/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field + * implementation may optionally normalize the input, but this should not be relied upon. */ +static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r); + +/** Verify whether a field element represents zero i.e. would normalize to a zero value. The field + * implementation may optionally normalize the input, but this should not be relied upon. */ +static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r); + +/** Set a field element equal to a small integer. Resulting field element is normalized. */ +static void secp256k1_fe_set_int(secp256k1_fe *r, int a); + +/** Sets a field element equal to zero, initializing all fields. */ +static void secp256k1_fe_clear(secp256k1_fe *a); + +/** Verify whether a field element is zero. Requires the input to be normalized. */ +static int secp256k1_fe_is_zero(const secp256k1_fe *a); + +/** Check the "oddness" of a field element. Requires the input to be normalized. */ +static int secp256k1_fe_is_odd(const secp256k1_fe *a); + +/** Compare two field elements. Requires magnitude-1 inputs. */ +static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b); + +/** Same as secp256k1_fe_equal, but may be variable time. */ +static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b); + +/** Compare two field elements. Requires both inputs to be normalized */ +static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); + +/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */ +static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a); + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a); + +/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input + * as an argument. The magnitude of the output is one higher. */ +static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m); + +/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that + * small integer. */ +static void secp256k1_fe_mul_int(secp256k1_fe *r, int a); + +/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */ +static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a); + +/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8. + * The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b); + +/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8. + * The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a); + +/** If a has a square root, it is computed in r and 1 is returned. If a does not + * have a square root, the root of its negation is computed and 0 is returned. + * The input's magnitude can be at most 8. The output magnitude is 1 (but not + * guaranteed to be normalized). The result in r will always be a square + * itself. */ +static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a); + +/** Checks whether a field element is a quadratic residue. */ +static int secp256k1_fe_is_quad_var(const secp256k1_fe *a); + +/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be + * at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */ +static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a); + +/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */ +static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a); + +/** Calculate the (modular) inverses of a batch of field elements. Requires the inputs' magnitudes to be + * at most 8. The output magnitudes are 1 (but not guaranteed to be normalized). The inputs and + * outputs must not overlap in memory. */ +static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len); + +/** Convert a field element to the storage type. */ +static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a); + +/** Convert a field element back from the storage type. */ +static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a); + +/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ +static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag); + +/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ +static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h new file mode 100644 index 00000000..61ee1e09 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26.h @@ -0,0 +1,47 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ + +#include + +typedef struct { + /* X = sum(i=0..9, elem[i]*2^26) mod n */ + uint32_t n[10]; +#ifdef VERIFY + int magnitude; + int normalized; +#endif +} secp256k1_fe; + +/* Unpacks a constant into a overlapping multi-limbed FE element. */ +#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ + (d0) & 0x3FFFFFFUL, \ + (((uint32_t)d0) >> 26) | (((uint32_t)(d1) & 0xFFFFFUL) << 6), \ + (((uint32_t)d1) >> 20) | (((uint32_t)(d2) & 0x3FFFUL) << 12), \ + (((uint32_t)d2) >> 14) | (((uint32_t)(d3) & 0xFFUL) << 18), \ + (((uint32_t)d3) >> 8) | (((uint32_t)(d4) & 0x3UL) << 24), \ + (((uint32_t)d4) >> 2) & 0x3FFFFFFUL, \ + (((uint32_t)d4) >> 28) | (((uint32_t)(d5) & 0x3FFFFFUL) << 4), \ + (((uint32_t)d5) >> 22) | (((uint32_t)(d6) & 0xFFFFUL) << 10), \ + (((uint32_t)d6) >> 16) | (((uint32_t)(d7) & 0x3FFUL) << 16), \ + (((uint32_t)d7) >> 10) \ +} + +#ifdef VERIFY +#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} +#else +#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} +#endif + +typedef struct { + uint32_t n[8]; +} secp256k1_fe_storage; + +#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }} +#define SECP256K1_FE_STORAGE_CONST_GET(d) d.n[7], d.n[6], d.n[5], d.n[4],d.n[3], d.n[2], d.n[1], d.n[0] +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h new file mode 100644 index 00000000..5fb092f1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_10x26_impl.h @@ -0,0 +1,1140 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ + +#include "util.h" +#include "num.h" +#include "field.h" + +#ifdef VERIFY +static void secp256k1_fe_verify(const secp256k1_fe *a) { + const uint32_t *d = a->n; + int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; + r &= (d[0] <= 0x3FFFFFFUL * m); + r &= (d[1] <= 0x3FFFFFFUL * m); + r &= (d[2] <= 0x3FFFFFFUL * m); + r &= (d[3] <= 0x3FFFFFFUL * m); + r &= (d[4] <= 0x3FFFFFFUL * m); + r &= (d[5] <= 0x3FFFFFFUL * m); + r &= (d[6] <= 0x3FFFFFFUL * m); + r &= (d[7] <= 0x3FFFFFFUL * m); + r &= (d[8] <= 0x3FFFFFFUL * m); + r &= (d[9] <= 0x03FFFFFUL * m); + r &= (a->magnitude >= 0); + r &= (a->magnitude <= 32); + if (a->normalized) { + r &= (a->magnitude <= 1); + if (r && (d[9] == 0x03FFFFFUL)) { + uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2]; + if (mid == 0x3FFFFFFUL) { + r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL); + } + } + } + VERIFY_CHECK(r == 1); +} +#endif + +static void secp256k1_fe_normalize(secp256k1_fe *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t m; + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) + & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); + + /* Apply the final reduction (for constant-time behaviour, we do it always) */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; + + /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ + VERIFY_CHECK(t9 >> 22 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t9 &= 0x03FFFFFUL; + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; + +#ifdef VERIFY + r->magnitude = 1; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_normalize_var(secp256k1_fe *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t m; + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL) + & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); + + if (x) { + t0 += 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; + + /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */ + VERIFY_CHECK(t9 >> 22 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t9 &= 0x03FFFFFUL; + } + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { + uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4], + t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9]; + + /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ + uint32_t z0, z1; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; t1 += (x << 6); + t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL; z0 = t0; z1 = t0 ^ 0x3D0UL; + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; + z0 |= t9; z1 &= t9 ^ 0x3C00000UL; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + return (z0 == 0) | (z1 == 0x3FFFFFFUL); +} + +static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { + uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9; + uint32_t z0, z1; + uint32_t x; + + t0 = r->n[0]; + t9 = r->n[9]; + + /* Reduce t9 at the start so there will be at most a single carry from the first pass */ + x = t9 >> 22; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x3D1UL; + + /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ + z0 = t0 & 0x3FFFFFFUL; + z1 = z0 ^ 0x3D0UL; + + /* Fast return path should catch the majority of cases */ + if ((z0 != 0UL) & (z1 != 0x3FFFFFFUL)) { + return 0; + } + + t1 = r->n[1]; + t2 = r->n[2]; + t3 = r->n[3]; + t4 = r->n[4]; + t5 = r->n[5]; + t6 = r->n[6]; + t7 = r->n[7]; + t8 = r->n[8]; + + t9 &= 0x03FFFFFUL; + t1 += (x << 6); + + t1 += (t0 >> 26); + t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL; z0 |= t1; z1 &= t1 ^ 0x40UL; + t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; z0 |= t2; z1 &= t2; + t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; z0 |= t3; z1 &= t3; + t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; z0 |= t4; z1 &= t4; + t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; z0 |= t5; z1 &= t5; + t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; z0 |= t6; z1 &= t6; + t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; z0 |= t7; z1 &= t7; + t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; z0 |= t8; z1 &= t8; + z0 |= t9; z1 &= t9 ^ 0x3C00000UL; + + /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t9 >> 23 == 0); + + return (z0 == 0) | (z1 == 0x3FFFFFFUL); +} + +SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { + r->n[0] = a; + r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { + const uint32_t *t = a->n; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0; +} + +SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return a->n[0] & 1; +} + +SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { + int i; +#ifdef VERIFY + a->magnitude = 0; + a->normalized = 1; +#endif + for (i=0; i<10; i++) { + a->n[i] = 0; + } +} + +static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { + int i; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + VERIFY_CHECK(b->normalized); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + for (i = 9; i >= 0; i--) { + if (a->n[i] > b->n[i]) { + return 1; + } + if (a->n[i] < b->n[i]) { + return -1; + } + } + return 0; +} + +static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { + int i; + r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; + r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0; + for (i=0; i<32; i++) { + int j; + for (j=0; j<4; j++) { + int limb = (8*i+2*j)/26; + int shift = (8*i+2*j)%26; + r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift; + } + } + if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) { + return 0; + } +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif + return 1; +} + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { + int i; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + for (i=0; i<32; i++) { + int j; + int c = 0; + for (j=0; j<4; j++) { + int limb = (8*i+2*j)/26; + int shift = (8*i+2*j)%26; + c |= ((a->n[limb] >> shift) & 0x3) << (2 * j); + } + r[31-i] = c; + } +} + +SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= m); + secp256k1_fe_verify(a); +#endif + r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0]; + r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1]; + r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2]; + r->n[3] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[3]; + r->n[4] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[4]; + r->n[5] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[5]; + r->n[6] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[6]; + r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7]; + r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8]; + r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9]; +#ifdef VERIFY + r->magnitude = m + 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { + r->n[0] *= a; + r->n[1] *= a; + r->n[2] *= a; + r->n[3] *= a; + r->n[4] *= a; + r->n[5] *= a; + r->n[6] *= a; + r->n[7] *= a; + r->n[8] *= a; + r->n[9] *= a; +#ifdef VERIFY + r->magnitude *= a; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { +#ifdef VERIFY + secp256k1_fe_verify(a); +#endif + r->n[0] += a->n[0]; + r->n[1] += a->n[1]; + r->n[2] += a->n[2]; + r->n[3] += a->n[3]; + r->n[4] += a->n[4]; + r->n[5] += a->n[5]; + r->n[6] += a->n[6]; + r->n[7] += a->n[7]; + r->n[8] += a->n[8]; + r->n[9] += a->n[9]; +#ifdef VERIFY + r->magnitude += a->magnitude; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +#if defined(USE_EXTERNAL_ASM) + +/* External assembler implementation */ +void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b); +void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a); + +#else + +#ifdef VERIFY +#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) +#else +#define VERIFY_BITS(x, n) do { } while(0) +#endif + +SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint32_t *r, const uint32_t *a, const uint32_t * SECP256K1_RESTRICT b) { + uint64_t c, d; + uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; + uint32_t t9, t1, t0, t2, t3, t4, t5, t6, t7; + const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; + + VERIFY_BITS(a[0], 30); + VERIFY_BITS(a[1], 30); + VERIFY_BITS(a[2], 30); + VERIFY_BITS(a[3], 30); + VERIFY_BITS(a[4], 30); + VERIFY_BITS(a[5], 30); + VERIFY_BITS(a[6], 30); + VERIFY_BITS(a[7], 30); + VERIFY_BITS(a[8], 30); + VERIFY_BITS(a[9], 26); + VERIFY_BITS(b[0], 30); + VERIFY_BITS(b[1], 30); + VERIFY_BITS(b[2], 30); + VERIFY_BITS(b[3], 30); + VERIFY_BITS(b[4], 30); + VERIFY_BITS(b[5], 30); + VERIFY_BITS(b[6], 30); + VERIFY_BITS(b[7], 30); + VERIFY_BITS(b[8], 30); + VERIFY_BITS(b[9], 26); + + /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. + * px is a shorthand for sum(a[i]*b[x-i], i=0..x). + * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. + */ + + d = (uint64_t)a[0] * b[9] + + (uint64_t)a[1] * b[8] + + (uint64_t)a[2] * b[7] + + (uint64_t)a[3] * b[6] + + (uint64_t)a[4] * b[5] + + (uint64_t)a[5] * b[4] + + (uint64_t)a[6] * b[3] + + (uint64_t)a[7] * b[2] + + (uint64_t)a[8] * b[1] + + (uint64_t)a[9] * b[0]; + /* VERIFY_BITS(d, 64); */ + /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + t9 = d & M; d >>= 26; + VERIFY_BITS(t9, 26); + VERIFY_BITS(d, 38); + /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + + c = (uint64_t)a[0] * b[0]; + VERIFY_BITS(c, 60); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ + d += (uint64_t)a[1] * b[9] + + (uint64_t)a[2] * b[8] + + (uint64_t)a[3] * b[7] + + (uint64_t)a[4] * b[6] + + (uint64_t)a[5] * b[5] + + (uint64_t)a[6] * b[4] + + (uint64_t)a[7] * b[3] + + (uint64_t)a[8] * b[2] + + (uint64_t)a[9] * b[1]; + VERIFY_BITS(d, 63); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + u0 = d & M; d >>= 26; c += u0 * R0; + VERIFY_BITS(u0, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 61); + /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + t0 = c & M; c >>= 26; c += u0 * R1; + VERIFY_BITS(t0, 26); + VERIFY_BITS(c, 37); + /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + + c += (uint64_t)a[0] * b[1] + + (uint64_t)a[1] * b[0]; + VERIFY_BITS(c, 62); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ + d += (uint64_t)a[2] * b[9] + + (uint64_t)a[3] * b[8] + + (uint64_t)a[4] * b[7] + + (uint64_t)a[5] * b[6] + + (uint64_t)a[6] * b[5] + + (uint64_t)a[7] * b[4] + + (uint64_t)a[8] * b[3] + + (uint64_t)a[9] * b[2]; + VERIFY_BITS(d, 63); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + u1 = d & M; d >>= 26; c += u1 * R0; + VERIFY_BITS(u1, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + t1 = c & M; c >>= 26; c += u1 * R1; + VERIFY_BITS(t1, 26); + VERIFY_BITS(c, 38); + /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + + c += (uint64_t)a[0] * b[2] + + (uint64_t)a[1] * b[1] + + (uint64_t)a[2] * b[0]; + VERIFY_BITS(c, 62); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + d += (uint64_t)a[3] * b[9] + + (uint64_t)a[4] * b[8] + + (uint64_t)a[5] * b[7] + + (uint64_t)a[6] * b[6] + + (uint64_t)a[7] * b[5] + + (uint64_t)a[8] * b[4] + + (uint64_t)a[9] * b[3]; + VERIFY_BITS(d, 63); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + u2 = d & M; d >>= 26; c += u2 * R0; + VERIFY_BITS(u2, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + t2 = c & M; c >>= 26; c += u2 * R1; + VERIFY_BITS(t2, 26); + VERIFY_BITS(c, 38); + /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[3] + + (uint64_t)a[1] * b[2] + + (uint64_t)a[2] * b[1] + + (uint64_t)a[3] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + d += (uint64_t)a[4] * b[9] + + (uint64_t)a[5] * b[8] + + (uint64_t)a[6] * b[7] + + (uint64_t)a[7] * b[6] + + (uint64_t)a[8] * b[5] + + (uint64_t)a[9] * b[4]; + VERIFY_BITS(d, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + u3 = d & M; d >>= 26; c += u3 * R0; + VERIFY_BITS(u3, 26); + VERIFY_BITS(d, 37); + /* VERIFY_BITS(c, 64); */ + /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + t3 = c & M; c >>= 26; c += u3 * R1; + VERIFY_BITS(t3, 26); + VERIFY_BITS(c, 39); + /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[4] + + (uint64_t)a[1] * b[3] + + (uint64_t)a[2] * b[2] + + (uint64_t)a[3] * b[1] + + (uint64_t)a[4] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[5] * b[9] + + (uint64_t)a[6] * b[8] + + (uint64_t)a[7] * b[7] + + (uint64_t)a[8] * b[6] + + (uint64_t)a[9] * b[5]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + u4 = d & M; d >>= 26; c += u4 * R0; + VERIFY_BITS(u4, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + t4 = c & M; c >>= 26; c += u4 * R1; + VERIFY_BITS(t4, 26); + VERIFY_BITS(c, 39); + /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[5] + + (uint64_t)a[1] * b[4] + + (uint64_t)a[2] * b[3] + + (uint64_t)a[3] * b[2] + + (uint64_t)a[4] * b[1] + + (uint64_t)a[5] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[6] * b[9] + + (uint64_t)a[7] * b[8] + + (uint64_t)a[8] * b[7] + + (uint64_t)a[9] * b[6]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + u5 = d & M; d >>= 26; c += u5 * R0; + VERIFY_BITS(u5, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + t5 = c & M; c >>= 26; c += u5 * R1; + VERIFY_BITS(t5, 26); + VERIFY_BITS(c, 39); + /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[6] + + (uint64_t)a[1] * b[5] + + (uint64_t)a[2] * b[4] + + (uint64_t)a[3] * b[3] + + (uint64_t)a[4] * b[2] + + (uint64_t)a[5] * b[1] + + (uint64_t)a[6] * b[0]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[7] * b[9] + + (uint64_t)a[8] * b[8] + + (uint64_t)a[9] * b[7]; + VERIFY_BITS(d, 61); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + u6 = d & M; d >>= 26; c += u6 * R0; + VERIFY_BITS(u6, 26); + VERIFY_BITS(d, 35); + /* VERIFY_BITS(c, 64); */ + /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + t6 = c & M; c >>= 26; c += u6 * R1; + VERIFY_BITS(t6, 26); + VERIFY_BITS(c, 39); + /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[7] + + (uint64_t)a[1] * b[6] + + (uint64_t)a[2] * b[5] + + (uint64_t)a[3] * b[4] + + (uint64_t)a[4] * b[3] + + (uint64_t)a[5] * b[2] + + (uint64_t)a[6] * b[1] + + (uint64_t)a[7] * b[0]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x8000007C00000007ULL); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[8] * b[9] + + (uint64_t)a[9] * b[8]; + VERIFY_BITS(d, 58); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + u7 = d & M; d >>= 26; c += u7 * R0; + VERIFY_BITS(u7, 26); + VERIFY_BITS(d, 32); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); + /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + t7 = c & M; c >>= 26; c += u7 * R1; + VERIFY_BITS(t7, 26); + VERIFY_BITS(c, 38); + /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)a[0] * b[8] + + (uint64_t)a[1] * b[7] + + (uint64_t)a[2] * b[6] + + (uint64_t)a[3] * b[5] + + (uint64_t)a[4] * b[4] + + (uint64_t)a[5] * b[3] + + (uint64_t)a[6] * b[2] + + (uint64_t)a[7] * b[1] + + (uint64_t)a[8] * b[0]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000007B80000008ULL); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[9] * b[9]; + VERIFY_BITS(d, 57); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + u8 = d & M; d >>= 26; c += u8 * R0; + VERIFY_BITS(u8, 26); + VERIFY_BITS(d, 31); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[3] = t3; + VERIFY_BITS(r[3], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = t4; + VERIFY_BITS(r[4], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[5] = t5; + VERIFY_BITS(r[5], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[6] = t6; + VERIFY_BITS(r[6], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[7] = t7; + VERIFY_BITS(r[7], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[8] = c & M; c >>= 26; c += u8 * R1; + VERIFY_BITS(r[8], 26); + VERIFY_BITS(c, 39); + /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R0 + t9; + VERIFY_BITS(c, 45); + /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); + VERIFY_BITS(r[9], 22); + VERIFY_BITS(c, 46); + /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + d = c * (R0 >> 4) + t0; + VERIFY_BITS(d, 56); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[0] = d & M; d >>= 26; + VERIFY_BITS(r[0], 26); + VERIFY_BITS(d, 30); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += c * (R1 >> 4) + t1; + VERIFY_BITS(d, 53); + VERIFY_CHECK(d <= 0x10000003FFFFBFULL); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[1] = d & M; d >>= 26; + VERIFY_BITS(r[1], 26); + VERIFY_BITS(d, 27); + VERIFY_CHECK(d <= 0x4000000ULL); + /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += t2; + VERIFY_BITS(d, 27); + /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = d; + VERIFY_BITS(r[2], 27); + /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t *a) { + uint64_t c, d; + uint64_t u0, u1, u2, u3, u4, u5, u6, u7, u8; + uint32_t t9, t0, t1, t2, t3, t4, t5, t6, t7; + const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL; + + VERIFY_BITS(a[0], 30); + VERIFY_BITS(a[1], 30); + VERIFY_BITS(a[2], 30); + VERIFY_BITS(a[3], 30); + VERIFY_BITS(a[4], 30); + VERIFY_BITS(a[5], 30); + VERIFY_BITS(a[6], 30); + VERIFY_BITS(a[7], 30); + VERIFY_BITS(a[8], 30); + VERIFY_BITS(a[9], 26); + + /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n. + * px is a shorthand for sum(a[i]*a[x-i], i=0..x). + * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0]. + */ + + d = (uint64_t)(a[0]*2) * a[9] + + (uint64_t)(a[1]*2) * a[8] + + (uint64_t)(a[2]*2) * a[7] + + (uint64_t)(a[3]*2) * a[6] + + (uint64_t)(a[4]*2) * a[5]; + /* VERIFY_BITS(d, 64); */ + /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + t9 = d & M; d >>= 26; + VERIFY_BITS(t9, 26); + VERIFY_BITS(d, 38); + /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */ + + c = (uint64_t)a[0] * a[0]; + VERIFY_BITS(c, 60); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */ + d += (uint64_t)(a[1]*2) * a[9] + + (uint64_t)(a[2]*2) * a[8] + + (uint64_t)(a[3]*2) * a[7] + + (uint64_t)(a[4]*2) * a[6] + + (uint64_t)a[5] * a[5]; + VERIFY_BITS(d, 63); + /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + u0 = d & M; d >>= 26; c += u0 * R0; + VERIFY_BITS(u0, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 61); + /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + t0 = c & M; c >>= 26; c += u0 * R1; + VERIFY_BITS(t0, 26); + VERIFY_BITS(c, 37); + /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */ + + c += (uint64_t)(a[0]*2) * a[1]; + VERIFY_BITS(c, 62); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */ + d += (uint64_t)(a[2]*2) * a[9] + + (uint64_t)(a[3]*2) * a[8] + + (uint64_t)(a[4]*2) * a[7] + + (uint64_t)(a[5]*2) * a[6]; + VERIFY_BITS(d, 63); + /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + u1 = d & M; d >>= 26; c += u1 * R0; + VERIFY_BITS(u1, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + t1 = c & M; c >>= 26; c += u1 * R1; + VERIFY_BITS(t1, 26); + VERIFY_BITS(c, 38); + /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[2] + + (uint64_t)a[1] * a[1]; + VERIFY_BITS(c, 62); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + d += (uint64_t)(a[3]*2) * a[9] + + (uint64_t)(a[4]*2) * a[8] + + (uint64_t)(a[5]*2) * a[7] + + (uint64_t)a[6] * a[6]; + VERIFY_BITS(d, 63); + /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + u2 = d & M; d >>= 26; c += u2 * R0; + VERIFY_BITS(u2, 26); + VERIFY_BITS(d, 37); + VERIFY_BITS(c, 63); + /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + t2 = c & M; c >>= 26; c += u2 * R1; + VERIFY_BITS(t2, 26); + VERIFY_BITS(c, 38); + /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[3] + + (uint64_t)(a[1]*2) * a[2]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + d += (uint64_t)(a[4]*2) * a[9] + + (uint64_t)(a[5]*2) * a[8] + + (uint64_t)(a[6]*2) * a[7]; + VERIFY_BITS(d, 63); + /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + u3 = d & M; d >>= 26; c += u3 * R0; + VERIFY_BITS(u3, 26); + VERIFY_BITS(d, 37); + /* VERIFY_BITS(c, 64); */ + /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + t3 = c & M; c >>= 26; c += u3 * R1; + VERIFY_BITS(t3, 26); + VERIFY_BITS(c, 39); + /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[4] + + (uint64_t)(a[1]*2) * a[3] + + (uint64_t)a[2] * a[2]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[5]*2) * a[9] + + (uint64_t)(a[6]*2) * a[8] + + (uint64_t)a[7] * a[7]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + u4 = d & M; d >>= 26; c += u4 * R0; + VERIFY_BITS(u4, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + t4 = c & M; c >>= 26; c += u4 * R1; + VERIFY_BITS(t4, 26); + VERIFY_BITS(c, 39); + /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[5] + + (uint64_t)(a[1]*2) * a[4] + + (uint64_t)(a[2]*2) * a[3]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[6]*2) * a[9] + + (uint64_t)(a[7]*2) * a[8]; + VERIFY_BITS(d, 62); + /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + u5 = d & M; d >>= 26; c += u5 * R0; + VERIFY_BITS(u5, 26); + VERIFY_BITS(d, 36); + /* VERIFY_BITS(c, 64); */ + /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + t5 = c & M; c >>= 26; c += u5 * R1; + VERIFY_BITS(t5, 26); + VERIFY_BITS(c, 39); + /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[6] + + (uint64_t)(a[1]*2) * a[5] + + (uint64_t)(a[2]*2) * a[4] + + (uint64_t)a[3] * a[3]; + VERIFY_BITS(c, 63); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[7]*2) * a[9] + + (uint64_t)a[8] * a[8]; + VERIFY_BITS(d, 61); + /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + u6 = d & M; d >>= 26; c += u6 * R0; + VERIFY_BITS(u6, 26); + VERIFY_BITS(d, 35); + /* VERIFY_BITS(c, 64); */ + /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + t6 = c & M; c >>= 26; c += u6 * R1; + VERIFY_BITS(t6, 26); + VERIFY_BITS(c, 39); + /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[7] + + (uint64_t)(a[1]*2) * a[6] + + (uint64_t)(a[2]*2) * a[5] + + (uint64_t)(a[3]*2) * a[4]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x8000007C00000007ULL); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)(a[8]*2) * a[9]; + VERIFY_BITS(d, 58); + /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + u7 = d & M; d >>= 26; c += u7 * R0; + VERIFY_BITS(u7, 26); + VERIFY_BITS(d, 32); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL); + /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + t7 = c & M; c >>= 26; c += u7 * R1; + VERIFY_BITS(t7, 26); + VERIFY_BITS(c, 38); + /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += (uint64_t)(a[0]*2) * a[8] + + (uint64_t)(a[1]*2) * a[7] + + (uint64_t)(a[2]*2) * a[6] + + (uint64_t)(a[3]*2) * a[5] + + (uint64_t)a[4] * a[4]; + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000007B80000008ULL); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint64_t)a[9] * a[9]; + VERIFY_BITS(d, 57); + /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + u8 = d & M; d >>= 26; c += u8 * R0; + VERIFY_BITS(u8, 26); + VERIFY_BITS(d, 31); + /* VERIFY_BITS(c, 64); */ + VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[3] = t3; + VERIFY_BITS(r[3], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = t4; + VERIFY_BITS(r[4], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[5] = t5; + VERIFY_BITS(r[5], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[6] = t6; + VERIFY_BITS(r[6], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[7] = t7; + VERIFY_BITS(r[7], 26); + /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + r[8] = c & M; c >>= 26; c += u8 * R1; + VERIFY_BITS(r[8], 26); + VERIFY_BITS(c, 39); + /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R0 + t9; + VERIFY_BITS(c, 45); + /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4); + VERIFY_BITS(r[9], 22); + VERIFY_BITS(c, 46); + /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + d = c * (R0 >> 4) + t0; + VERIFY_BITS(d, 56); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[0] = d & M; d >>= 26; + VERIFY_BITS(r[0], 26); + VERIFY_BITS(d, 30); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += c * (R1 >> 4) + t1; + VERIFY_BITS(d, 53); + VERIFY_CHECK(d <= 0x10000003FFFFBFULL); + /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[1] = d & M; d >>= 26; + VERIFY_BITS(r[1], 26); + VERIFY_BITS(d, 27); + VERIFY_CHECK(d <= 0x4000000ULL); + /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + d += t2; + VERIFY_BITS(d, 27); + /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = d; + VERIFY_BITS(r[2], 27); + /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} +#endif + +static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + VERIFY_CHECK(b->magnitude <= 8); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); + VERIFY_CHECK(r != b); +#endif + secp256k1_fe_mul_inner(r->n, a->n, b->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + secp256k1_fe_verify(a); +#endif + secp256k1_fe_sqr_inner(r->n, a->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { + uint32_t mask0, mask1; + mask0 = flag + ~((uint32_t)0); + mask1 = ~mask0; + r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); + r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); + r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); + r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); + r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); + r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); + r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); + r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); + r->n[8] = (r->n[8] & mask0) | (a->n[8] & mask1); + r->n[9] = (r->n[9] & mask0) | (a->n[9] & mask1); +#ifdef VERIFY + if (a->magnitude > r->magnitude) { + r->magnitude = a->magnitude; + } + r->normalized &= a->normalized; +#endif +} + +static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { + uint32_t mask0, mask1; + mask0 = flag + ~((uint32_t)0); + mask1 = ~mask0; + r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); + r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); + r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); + r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); + r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); + r->n[5] = (r->n[5] & mask0) | (a->n[5] & mask1); + r->n[6] = (r->n[6] & mask0) | (a->n[6] & mask1); + r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1); +} + +static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); +#endif + r->n[0] = a->n[0] | a->n[1] << 26; + r->n[1] = a->n[1] >> 6 | a->n[2] << 20; + r->n[2] = a->n[2] >> 12 | a->n[3] << 14; + r->n[3] = a->n[3] >> 18 | a->n[4] << 8; + r->n[4] = a->n[4] >> 24 | a->n[5] << 2 | a->n[6] << 28; + r->n[5] = a->n[6] >> 4 | a->n[7] << 22; + r->n[6] = a->n[7] >> 10 | a->n[8] << 16; + r->n[7] = a->n[8] >> 16 | a->n[9] << 10; +} + +static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { + r->n[0] = a->n[0] & 0x3FFFFFFUL; + r->n[1] = a->n[0] >> 26 | ((a->n[1] << 6) & 0x3FFFFFFUL); + r->n[2] = a->n[1] >> 20 | ((a->n[2] << 12) & 0x3FFFFFFUL); + r->n[3] = a->n[2] >> 14 | ((a->n[3] << 18) & 0x3FFFFFFUL); + r->n[4] = a->n[3] >> 8 | ((a->n[4] << 24) & 0x3FFFFFFUL); + r->n[5] = (a->n[4] >> 2) & 0x3FFFFFFUL; + r->n[6] = a->n[4] >> 28 | ((a->n[5] << 4) & 0x3FFFFFFUL); + r->n[7] = a->n[5] >> 22 | ((a->n[6] << 10) & 0x3FFFFFFUL); + r->n[8] = a->n[6] >> 16 | ((a->n[7] << 16) & 0x3FFFFFFUL); + r->n[9] = a->n[7] >> 10; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; +#endif +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h new file mode 100644 index 00000000..8e69a560 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52.h @@ -0,0 +1,47 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_ +#define _SECP256K1_FIELD_REPR_ + +#include + +typedef struct { + /* X = sum(i=0..4, elem[i]*2^52) mod n */ + uint64_t n[5]; +#ifdef VERIFY + int magnitude; + int normalized; +#endif +} secp256k1_fe; + +/* Unpacks a constant into a overlapping multi-limbed FE element. */ +#define SECP256K1_FE_CONST_INNER(d7, d6, d5, d4, d3, d2, d1, d0) { \ + (d0) | (((uint64_t)(d1) & 0xFFFFFUL) << 32), \ + ((uint64_t)(d1) >> 20) | (((uint64_t)(d2)) << 12) | (((uint64_t)(d3) & 0xFFUL) << 44), \ + ((uint64_t)(d3) >> 8) | (((uint64_t)(d4) & 0xFFFFFFFUL) << 24), \ + ((uint64_t)(d4) >> 28) | (((uint64_t)(d5)) << 4) | (((uint64_t)(d6) & 0xFFFFUL) << 36), \ + ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \ +} + +#ifdef VERIFY +#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1} +#else +#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))} +#endif + +typedef struct { + uint64_t n[4]; +} secp256k1_fe_storage; + +#define SECP256K1_FE_STORAGE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{ \ + (d0) | (((uint64_t)(d1)) << 32), \ + (d2) | (((uint64_t)(d3)) << 32), \ + (d4) | (((uint64_t)(d5)) << 32), \ + (d6) | (((uint64_t)(d7)) << 32) \ +}} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h new file mode 100644 index 00000000..98cc004b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_asm_impl.h @@ -0,0 +1,502 @@ +/********************************************************************** + * Copyright (c) 2013-2014 Diederik Huys, Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +/** + * Changelog: + * - March 2013, Diederik Huys: original version + * - November 2014, Pieter Wuille: updated to use Peter Dettman's parallel multiplication algorithm + * - December 2014, Pieter Wuille: converted from YASM to GCC inline assembly + */ + +#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ + +SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { +/** + * Registers: rdx:rax = multiplication accumulator + * r9:r8 = c + * r15:rcx = d + * r10-r14 = a0-a4 + * rbx = b + * rdi = r + * rsi = a / t? + */ + uint64_t tmp1, tmp2, tmp3; +__asm__ __volatile__( + "movq 0(%%rsi),%%r10\n" + "movq 8(%%rsi),%%r11\n" + "movq 16(%%rsi),%%r12\n" + "movq 24(%%rsi),%%r13\n" + "movq 32(%%rsi),%%r14\n" + + /* d += a3 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r13\n" + "movq %%rax,%%rcx\n" + "movq %%rdx,%%r15\n" + /* d += a2 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a1 * b2 */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d = a0 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r10\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* c = a4 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r14\n" + "movq %%rax,%%r8\n" + "movq %%rdx,%%r9\n" + /* d += (c & M) * R */ + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* c >>= 52 (%%r8 only) */ + "shrdq $52,%%r9,%%r8\n" + /* t3 (tmp1) = d & M */ + "movq %%rcx,%%rsi\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rsi\n" + "movq %%rsi,%q1\n" + /* d >>= 52 */ + "shrdq $52,%%r15,%%rcx\n" + "xorq %%r15,%%r15\n" + /* d += a4 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a3 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a2 * b2 */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a1 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a0 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r10\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += c * R */ + "movq %%r8,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* t4 = d & M (%%rsi) */ + "movq %%rcx,%%rsi\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rsi\n" + /* d >>= 52 */ + "shrdq $52,%%r15,%%rcx\n" + "xorq %%r15,%%r15\n" + /* tx = t4 >> 48 (tmp3) */ + "movq %%rsi,%%rax\n" + "shrq $48,%%rax\n" + "movq %%rax,%q3\n" + /* t4 &= (M >> 4) (tmp2) */ + "movq $0xffffffffffff,%%rax\n" + "andq %%rax,%%rsi\n" + "movq %%rsi,%q2\n" + /* c = a0 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r10\n" + "movq %%rax,%%r8\n" + "movq %%rdx,%%r9\n" + /* d += a4 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a3 * b2 */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a2 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a1 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* u0 = d & M (%%rsi) */ + "movq %%rcx,%%rsi\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rsi\n" + /* d >>= 52 */ + "shrdq $52,%%r15,%%rcx\n" + "xorq %%r15,%%r15\n" + /* u0 = (u0 << 4) | tx (%%rsi) */ + "shlq $4,%%rsi\n" + "movq %q3,%%rax\n" + "orq %%rax,%%rsi\n" + /* c += u0 * (R >> 4) */ + "movq $0x1000003d1,%%rax\n" + "mulq %%rsi\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* r[0] = c & M */ + "movq %%r8,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq %%rax,0(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += a1 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* c += a0 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r10\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d += a4 * b2 */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a3 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a2 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* c += (d & M) * R */ + "movq %%rcx,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d >>= 52 */ + "shrdq $52,%%r15,%%rcx\n" + "xorq %%r15,%%r15\n" + /* r[1] = c & M */ + "movq %%r8,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq %%rax,8(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += a2 * b0 */ + "movq 0(%%rbx),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* c += a1 * b1 */ + "movq 8(%%rbx),%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* c += a0 * b2 (last use of %%r10 = a0) */ + "movq 16(%%rbx),%%rax\n" + "mulq %%r10\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* fetch t3 (%%r10, overwrites a0), t4 (%%rsi) */ + "movq %q2,%%rsi\n" + "movq %q1,%%r10\n" + /* d += a4 * b3 */ + "movq 24(%%rbx),%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* d += a3 * b4 */ + "movq 32(%%rbx),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rcx\n" + "adcq %%rdx,%%r15\n" + /* c += (d & M) * R */ + "movq %%rcx,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d >>= 52 (%%rcx only) */ + "shrdq $52,%%r15,%%rcx\n" + /* r[2] = c & M */ + "movq %%r8,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq %%rax,16(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += t3 */ + "addq %%r10,%%r8\n" + /* c += d * R */ + "movq %%rcx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* r[3] = c & M */ + "movq %%r8,%%rax\n" + "movq $0xfffffffffffff,%%rdx\n" + "andq %%rdx,%%rax\n" + "movq %%rax,24(%%rdi)\n" + /* c >>= 52 (%%r8 only) */ + "shrdq $52,%%r9,%%r8\n" + /* c += t4 (%%r8 only) */ + "addq %%rsi,%%r8\n" + /* r[4] = c */ + "movq %%r8,32(%%rdi)\n" +: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) +: "b"(b), "D"(r) +: "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" +); +} + +SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { +/** + * Registers: rdx:rax = multiplication accumulator + * r9:r8 = c + * rcx:rbx = d + * r10-r14 = a0-a4 + * r15 = M (0xfffffffffffff) + * rdi = r + * rsi = a / t? + */ + uint64_t tmp1, tmp2, tmp3; +__asm__ __volatile__( + "movq 0(%%rsi),%%r10\n" + "movq 8(%%rsi),%%r11\n" + "movq 16(%%rsi),%%r12\n" + "movq 24(%%rsi),%%r13\n" + "movq 32(%%rsi),%%r14\n" + "movq $0xfffffffffffff,%%r15\n" + + /* d = (a0*2) * a3 */ + "leaq (%%r10,%%r10,1),%%rax\n" + "mulq %%r13\n" + "movq %%rax,%%rbx\n" + "movq %%rdx,%%rcx\n" + /* d += (a1*2) * a2 */ + "leaq (%%r11,%%r11,1),%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* c = a4 * a4 */ + "movq %%r14,%%rax\n" + "mulq %%r14\n" + "movq %%rax,%%r8\n" + "movq %%rdx,%%r9\n" + /* d += (c & M) * R */ + "andq %%r15,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* c >>= 52 (%%r8 only) */ + "shrdq $52,%%r9,%%r8\n" + /* t3 (tmp1) = d & M */ + "movq %%rbx,%%rsi\n" + "andq %%r15,%%rsi\n" + "movq %%rsi,%q1\n" + /* d >>= 52 */ + "shrdq $52,%%rcx,%%rbx\n" + "xorq %%rcx,%%rcx\n" + /* a4 *= 2 */ + "addq %%r14,%%r14\n" + /* d += a0 * a4 */ + "movq %%r10,%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d+= (a1*2) * a3 */ + "leaq (%%r11,%%r11,1),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d += a2 * a2 */ + "movq %%r12,%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d += c * R */ + "movq %%r8,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* t4 = d & M (%%rsi) */ + "movq %%rbx,%%rsi\n" + "andq %%r15,%%rsi\n" + /* d >>= 52 */ + "shrdq $52,%%rcx,%%rbx\n" + "xorq %%rcx,%%rcx\n" + /* tx = t4 >> 48 (tmp3) */ + "movq %%rsi,%%rax\n" + "shrq $48,%%rax\n" + "movq %%rax,%q3\n" + /* t4 &= (M >> 4) (tmp2) */ + "movq $0xffffffffffff,%%rax\n" + "andq %%rax,%%rsi\n" + "movq %%rsi,%q2\n" + /* c = a0 * a0 */ + "movq %%r10,%%rax\n" + "mulq %%r10\n" + "movq %%rax,%%r8\n" + "movq %%rdx,%%r9\n" + /* d += a1 * a4 */ + "movq %%r11,%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d += (a2*2) * a3 */ + "leaq (%%r12,%%r12,1),%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* u0 = d & M (%%rsi) */ + "movq %%rbx,%%rsi\n" + "andq %%r15,%%rsi\n" + /* d >>= 52 */ + "shrdq $52,%%rcx,%%rbx\n" + "xorq %%rcx,%%rcx\n" + /* u0 = (u0 << 4) | tx (%%rsi) */ + "shlq $4,%%rsi\n" + "movq %q3,%%rax\n" + "orq %%rax,%%rsi\n" + /* c += u0 * (R >> 4) */ + "movq $0x1000003d1,%%rax\n" + "mulq %%rsi\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* r[0] = c & M */ + "movq %%r8,%%rax\n" + "andq %%r15,%%rax\n" + "movq %%rax,0(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* a0 *= 2 */ + "addq %%r10,%%r10\n" + /* c += a0 * a1 */ + "movq %%r10,%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d += a2 * a4 */ + "movq %%r12,%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* d += a3 * a3 */ + "movq %%r13,%%rax\n" + "mulq %%r13\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* c += (d & M) * R */ + "movq %%rbx,%%rax\n" + "andq %%r15,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d >>= 52 */ + "shrdq $52,%%rcx,%%rbx\n" + "xorq %%rcx,%%rcx\n" + /* r[1] = c & M */ + "movq %%r8,%%rax\n" + "andq %%r15,%%rax\n" + "movq %%rax,8(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += a0 * a2 (last use of %%r10) */ + "movq %%r10,%%rax\n" + "mulq %%r12\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* fetch t3 (%%r10, overwrites a0),t4 (%%rsi) */ + "movq %q2,%%rsi\n" + "movq %q1,%%r10\n" + /* c += a1 * a1 */ + "movq %%r11,%%rax\n" + "mulq %%r11\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d += a3 * a4 */ + "movq %%r13,%%rax\n" + "mulq %%r14\n" + "addq %%rax,%%rbx\n" + "adcq %%rdx,%%rcx\n" + /* c += (d & M) * R */ + "movq %%rbx,%%rax\n" + "andq %%r15,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* d >>= 52 (%%rbx only) */ + "shrdq $52,%%rcx,%%rbx\n" + /* r[2] = c & M */ + "movq %%r8,%%rax\n" + "andq %%r15,%%rax\n" + "movq %%rax,16(%%rdi)\n" + /* c >>= 52 */ + "shrdq $52,%%r9,%%r8\n" + "xorq %%r9,%%r9\n" + /* c += t3 */ + "addq %%r10,%%r8\n" + /* c += d * R */ + "movq %%rbx,%%rax\n" + "movq $0x1000003d10,%%rdx\n" + "mulq %%rdx\n" + "addq %%rax,%%r8\n" + "adcq %%rdx,%%r9\n" + /* r[3] = c & M */ + "movq %%r8,%%rax\n" + "andq %%r15,%%rax\n" + "movq %%rax,24(%%rdi)\n" + /* c >>= 52 (%%r8 only) */ + "shrdq $52,%%r9,%%r8\n" + /* c += t4 (%%r8 only) */ + "addq %%rsi,%%r8\n" + /* r[4] = c */ + "movq %%r8,32(%%rdi)\n" +: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3) +: "D"(r) +: "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory" +); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h new file mode 100644 index 00000000..dd88f38c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_impl.h @@ -0,0 +1,451 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_REPR_IMPL_H_ +#define _SECP256K1_FIELD_REPR_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include "util.h" +#include "num.h" +#include "field.h" + +#if defined(USE_ASM_X86_64) +#include "field_5x52_asm_impl.h" +#else +#include "field_5x52_int128_impl.h" +#endif + +/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F, + * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, + * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element + * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations + * accept any input with magnitude at most M, and have different rules for propagating magnitude to their + * output. + */ + +#ifdef VERIFY +static void secp256k1_fe_verify(const secp256k1_fe *a) { + const uint64_t *d = a->n; + int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; + /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ + r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m); + r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m); + r &= (a->magnitude >= 0); + r &= (a->magnitude <= 2048); + if (a->normalized) { + r &= (a->magnitude <= 1); + if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { + r &= (d[0] < 0xFFFFEFFFFFC2FULL); + } + } + VERIFY_CHECK(r == 1); +} +#endif + +static void secp256k1_fe_normalize(secp256k1_fe *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t m; + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) + & (t0 >= 0xFFFFEFFFFFC2FULL)); + + /* Apply the final reduction (for constant-time behaviour, we do it always) */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; + + /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ + VERIFY_CHECK(t4 >> 48 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t4 &= 0x0FFFFFFFFFFFFULL; + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + +#ifdef VERIFY + r->magnitude = 1; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_normalize_var(secp256k1_fe *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t m; + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + /* At most a single final reduction is needed; check if the value is >= the field characteristic */ + x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) + & (t0 >= 0xFFFFEFFFFFC2FULL)); + + if (x) { + t0 += 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; + + /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ + VERIFY_CHECK(t4 >> 48 == x); + + /* Mask off the possible multiple of 2^256 from the final reduction */ + t4 &= 0x0FFFFFFFFFFFFULL; + } + + r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; + +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { + uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; + + /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ + uint64_t z0, z1; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL; + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; + z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); +} + +static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { + uint64_t t0, t1, t2, t3, t4; + uint64_t z0, z1; + uint64_t x; + + t0 = r->n[0]; + t4 = r->n[4]; + + /* Reduce t4 at the start so there will be at most a single carry from the first pass */ + x = t4 >> 48; + + /* The first pass ensures the magnitude is 1, ... */ + t0 += x * 0x1000003D1ULL; + + /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ + z0 = t0 & 0xFFFFFFFFFFFFFULL; + z1 = z0 ^ 0x1000003D0ULL; + + /* Fast return path should catch the majority of cases */ + if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) { + return 0; + } + + t1 = r->n[1]; + t2 = r->n[2]; + t3 = r->n[3]; + + t4 &= 0x0FFFFFFFFFFFFULL; + + t1 += (t0 >> 52); + t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; + t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; + t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; + z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; + + /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ + VERIFY_CHECK(t4 >> 49 == 0); + + return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); +} + +SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { + r->n[0] = a; + r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { + const uint64_t *t = a->n; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; +} + +SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + return a->n[0] & 1; +} + +SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { + int i; +#ifdef VERIFY + a->magnitude = 0; + a->normalized = 1; +#endif + for (i=0; i<5; i++) { + a->n[i] = 0; + } +} + +static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { + int i; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + VERIFY_CHECK(b->normalized); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); +#endif + for (i = 4; i >= 0; i--) { + if (a->n[i] > b->n[i]) { + return 1; + } + if (a->n[i] < b->n[i]) { + return -1; + } + } + return 0; +} + +static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { + int i; + r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; + for (i=0; i<32; i++) { + int j; + for (j=0; j<2; j++) { + int limb = (8*i+4*j)/52; + int shift = (8*i+4*j)%52; + r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift; + } + } + if (r->n[4] == 0x0FFFFFFFFFFFFULL && (r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL && r->n[0] >= 0xFFFFEFFFFFC2FULL) { + return 0; + } +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; + secp256k1_fe_verify(r); +#endif + return 1; +} + +/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ +static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { + int i; +#ifdef VERIFY + VERIFY_CHECK(a->normalized); + secp256k1_fe_verify(a); +#endif + for (i=0; i<32; i++) { + int j; + int c = 0; + for (j=0; j<2; j++) { + int limb = (8*i+4*j)/52; + int shift = (8*i+4*j)%52; + c |= ((a->n[limb] >> shift) & 0xF) << (4 * j); + } + r[31-i] = c; + } +} + +SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= m); + secp256k1_fe_verify(a); +#endif + r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; + r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; + r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2]; + r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3]; + r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; +#ifdef VERIFY + r->magnitude = m + 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { + r->n[0] *= a; + r->n[1] *= a; + r->n[2] *= a; + r->n[3] *= a; + r->n[4] *= a; +#ifdef VERIFY + r->magnitude *= a; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { +#ifdef VERIFY + secp256k1_fe_verify(a); +#endif + r->n[0] += a->n[0]; + r->n[1] += a->n[1]; + r->n[2] += a->n[2]; + r->n[3] += a->n[3]; + r->n[4] += a->n[4]; +#ifdef VERIFY + r->magnitude += a->magnitude; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + VERIFY_CHECK(b->magnitude <= 8); + secp256k1_fe_verify(a); + secp256k1_fe_verify(b); + VERIFY_CHECK(r != b); +#endif + secp256k1_fe_mul_inner(r->n, a->n, b->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->magnitude <= 8); + secp256k1_fe_verify(a); +#endif + secp256k1_fe_sqr_inner(r->n, a->n); +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 0; + secp256k1_fe_verify(r); +#endif +} + +static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { + uint64_t mask0, mask1; + mask0 = flag + ~((uint64_t)0); + mask1 = ~mask0; + r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); + r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); + r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); + r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); + r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); +#ifdef VERIFY + if (a->magnitude > r->magnitude) { + r->magnitude = a->magnitude; + } + r->normalized &= a->normalized; +#endif +} + +static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { + uint64_t mask0, mask1; + mask0 = flag + ~((uint64_t)0); + mask1 = ~mask0; + r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); + r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); + r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); + r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); +} + +static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { +#ifdef VERIFY + VERIFY_CHECK(a->normalized); +#endif + r->n[0] = a->n[0] | a->n[1] << 52; + r->n[1] = a->n[1] >> 12 | a->n[2] << 40; + r->n[2] = a->n[2] >> 24 | a->n[3] << 28; + r->n[3] = a->n[3] >> 36 | a->n[4] << 16; +} + +static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { + r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL; + r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL); + r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL); + r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL); + r->n[4] = a->n[3] >> 16; +#ifdef VERIFY + r->magnitude = 1; + r->normalized = 1; +#endif +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h new file mode 100644 index 00000000..0bf22bdd --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_5x52_int128_impl.h @@ -0,0 +1,277 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_INNER5X52_IMPL_H_ +#define _SECP256K1_FIELD_INNER5X52_IMPL_H_ + +#include + +#ifdef VERIFY +#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0) +#else +#define VERIFY_BITS(x, n) do { } while(0) +#endif + +SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) { + uint128_t c, d; + uint64_t t3, t4, tx, u0; + uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; + const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; + + VERIFY_BITS(a[0], 56); + VERIFY_BITS(a[1], 56); + VERIFY_BITS(a[2], 56); + VERIFY_BITS(a[3], 56); + VERIFY_BITS(a[4], 52); + VERIFY_BITS(b[0], 56); + VERIFY_BITS(b[1], 56); + VERIFY_BITS(b[2], 56); + VERIFY_BITS(b[3], 56); + VERIFY_BITS(b[4], 52); + VERIFY_CHECK(r != b); + + /* [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. + * px is a shorthand for sum(a[i]*b[x-i], i=0..x). + * Note that [x 0 0 0 0 0] = [x*R]. + */ + + d = (uint128_t)a0 * b[3] + + (uint128_t)a1 * b[2] + + (uint128_t)a2 * b[1] + + (uint128_t)a3 * b[0]; + VERIFY_BITS(d, 114); + /* [d 0 0 0] = [p3 0 0 0] */ + c = (uint128_t)a4 * b[4]; + VERIFY_BITS(c, 112); + /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + d += (c & M) * R; c >>= 52; + VERIFY_BITS(d, 115); + VERIFY_BITS(c, 60); + /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + t3 = d & M; d >>= 52; + VERIFY_BITS(t3, 52); + VERIFY_BITS(d, 63); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + + d += (uint128_t)a0 * b[4] + + (uint128_t)a1 * b[3] + + (uint128_t)a2 * b[2] + + (uint128_t)a3 * b[1] + + (uint128_t)a4 * b[0]; + VERIFY_BITS(d, 115); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + d += c * R; + VERIFY_BITS(d, 116); + /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + t4 = d & M; d >>= 52; + VERIFY_BITS(t4, 52); + VERIFY_BITS(d, 64); + /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + tx = (t4 >> 48); t4 &= (M >> 4); + VERIFY_BITS(tx, 4); + VERIFY_BITS(t4, 48); + /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + + c = (uint128_t)a0 * b[0]; + VERIFY_BITS(c, 112); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ + d += (uint128_t)a1 * b[4] + + (uint128_t)a2 * b[3] + + (uint128_t)a3 * b[2] + + (uint128_t)a4 * b[1]; + VERIFY_BITS(d, 115); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = d & M; d >>= 52; + VERIFY_BITS(u0, 52); + VERIFY_BITS(d, 63); + /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = (u0 << 4) | tx; + VERIFY_BITS(u0, 56); + /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + c += (uint128_t)u0 * (R >> 4); + VERIFY_BITS(c, 115); + /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + r[0] = c & M; c >>= 52; + VERIFY_BITS(r[0], 52); + VERIFY_BITS(c, 61); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ + + c += (uint128_t)a0 * b[1] + + (uint128_t)a1 * b[0]; + VERIFY_BITS(c, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ + d += (uint128_t)a2 * b[4] + + (uint128_t)a3 * b[3] + + (uint128_t)a4 * b[2]; + VERIFY_BITS(d, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + r[1] = c & M; c >>= 52; + VERIFY_BITS(r[1], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + + c += (uint128_t)a0 * b[2] + + (uint128_t)a1 * b[1] + + (uint128_t)a2 * b[0]; + VERIFY_BITS(c, 114); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint128_t)a3 * b[4] + + (uint128_t)a4 * b[3]; + VERIFY_BITS(d, 114); + /* [d 0 0 t4 t3 c t1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = c & M; c >>= 52; + VERIFY_BITS(r[2], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += d * R + t3; + VERIFY_BITS(c, 100); + /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[3] = c & M; c >>= 52; + VERIFY_BITS(r[3], 52); + VERIFY_BITS(c, 48); + /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += t4; + VERIFY_BITS(c, 49); + /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = c; + VERIFY_BITS(r[4], 49); + /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) { + uint128_t c, d; + uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4]; + int64_t t3, t4, tx, u0; + const uint64_t M = 0xFFFFFFFFFFFFFULL, R = 0x1000003D10ULL; + + VERIFY_BITS(a[0], 56); + VERIFY_BITS(a[1], 56); + VERIFY_BITS(a[2], 56); + VERIFY_BITS(a[3], 56); + VERIFY_BITS(a[4], 52); + + /** [... a b c] is a shorthand for ... + a<<104 + b<<52 + c<<0 mod n. + * px is a shorthand for sum(a[i]*a[x-i], i=0..x). + * Note that [x 0 0 0 0 0] = [x*R]. + */ + + d = (uint128_t)(a0*2) * a3 + + (uint128_t)(a1*2) * a2; + VERIFY_BITS(d, 114); + /* [d 0 0 0] = [p3 0 0 0] */ + c = (uint128_t)a4 * a4; + VERIFY_BITS(c, 112); + /* [c 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + d += (c & M) * R; c >>= 52; + VERIFY_BITS(d, 115); + VERIFY_BITS(c, 60); + /* [c 0 0 0 0 0 d 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + t3 = d & M; d >>= 52; + VERIFY_BITS(t3, 52); + VERIFY_BITS(d, 63); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 0 p3 0 0 0] */ + + a4 *= 2; + d += (uint128_t)a0 * a4 + + (uint128_t)(a1*2) * a3 + + (uint128_t)a2 * a2; + VERIFY_BITS(d, 115); + /* [c 0 0 0 0 d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + d += c * R; + VERIFY_BITS(d, 116); + /* [d t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + t4 = d & M; d >>= 52; + VERIFY_BITS(t4, 52); + VERIFY_BITS(d, 64); + /* [d t4 t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + tx = (t4 >> 48); t4 &= (M >> 4); + VERIFY_BITS(tx, 4); + VERIFY_BITS(t4, 48); + /* [d t4+(tx<<48) t3 0 0 0] = [p8 0 0 0 p4 p3 0 0 0] */ + + c = (uint128_t)a0 * a0; + VERIFY_BITS(c, 112); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 0 p4 p3 0 0 p0] */ + d += (uint128_t)a1 * a4 + + (uint128_t)(a2*2) * a3; + VERIFY_BITS(d, 114); + /* [d t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = d & M; d >>= 52; + VERIFY_BITS(u0, 52); + VERIFY_BITS(d, 62); + /* [d u0 t4+(tx<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + /* [d 0 t4+(tx<<48)+(u0<<52) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + u0 = (u0 << 4) | tx; + VERIFY_BITS(u0, 56); + /* [d 0 t4+(u0<<48) t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + c += (uint128_t)u0 * (R >> 4); + VERIFY_BITS(c, 113); + /* [d 0 t4 t3 0 0 c] = [p8 0 0 p5 p4 p3 0 0 p0] */ + r[0] = c & M; c >>= 52; + VERIFY_BITS(r[0], 52); + VERIFY_BITS(c, 61); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 0 p0] */ + + a0 *= 2; + c += (uint128_t)a0 * a1; + VERIFY_BITS(c, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 0 p5 p4 p3 0 p1 p0] */ + d += (uint128_t)a2 * a4 + + (uint128_t)a3 * a3; + VERIFY_BITS(d, 114); + /* [d 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 t4 t3 0 c r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + r[1] = c & M; c >>= 52; + VERIFY_BITS(r[1], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 0 p1 p0] */ + + c += (uint128_t)a0 * a2 + + (uint128_t)a1 * a1; + VERIFY_BITS(c, 114); + /* [d 0 0 t4 t3 c r1 r0] = [p8 0 p6 p5 p4 p3 p2 p1 p0] */ + d += (uint128_t)a3 * a4; + VERIFY_BITS(d, 114); + /* [d 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += (d & M) * R; d >>= 52; + VERIFY_BITS(c, 115); + VERIFY_BITS(d, 62); + /* [d 0 0 0 t4 t3 c r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[2] = c & M; c >>= 52; + VERIFY_BITS(r[2], 52); + VERIFY_BITS(c, 63); + /* [d 0 0 0 t4 t3+c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + + c += d * R + t3; + VERIFY_BITS(c, 100); + /* [t4 c r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[3] = c & M; c >>= 52; + VERIFY_BITS(r[3], 52); + VERIFY_BITS(c, 48); + /* [t4+c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + c += t4; + VERIFY_BITS(c, 49); + /* [c r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ + r[4] = c; + VERIFY_BITS(r[4], 49); + /* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */ +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h new file mode 100644 index 00000000..5127b279 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/field_impl.h @@ -0,0 +1,315 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_FIELD_IMPL_H_ +#define _SECP256K1_FIELD_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include "util.h" + +#if defined(USE_FIELD_10X26) +#include "field_10x26_impl.h" +#elif defined(USE_FIELD_5X52) +#include "field_5x52_impl.h" +#else +#error "Please select field implementation" +#endif + +SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe na; + secp256k1_fe_negate(&na, a, 1); + secp256k1_fe_add(&na, b); + return secp256k1_fe_normalizes_to_zero(&na); +} + +SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe na; + secp256k1_fe_negate(&na, a, 1); + secp256k1_fe_add(&na, b); + return secp256k1_fe_normalizes_to_zero_var(&na); +} + +static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) { + /** Given that p is congruent to 3 mod 4, we can compute the square root of + * a mod p as the (p+1)/4'th power of a. + * + * As (p+1)/4 is an even number, it will have the same result for a and for + * (-a). Only one of these two numbers actually has a square root however, + * so we test at the end by squaring and comparing to the input. + * Also because (p+1)/4 is an even number, the computed square root is + * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)). + */ + secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; + int j; + + /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in + * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: + * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] + */ + + secp256k1_fe_sqr(&x2, a); + secp256k1_fe_mul(&x2, &x2, a); + + secp256k1_fe_sqr(&x3, &x2); + secp256k1_fe_mul(&x3, &x3, a); + + x6 = x3; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x6, &x6); + } + secp256k1_fe_mul(&x6, &x6, &x3); + + x9 = x6; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x9, &x9); + } + secp256k1_fe_mul(&x9, &x9, &x3); + + x11 = x9; + for (j=0; j<2; j++) { + secp256k1_fe_sqr(&x11, &x11); + } + secp256k1_fe_mul(&x11, &x11, &x2); + + x22 = x11; + for (j=0; j<11; j++) { + secp256k1_fe_sqr(&x22, &x22); + } + secp256k1_fe_mul(&x22, &x22, &x11); + + x44 = x22; + for (j=0; j<22; j++) { + secp256k1_fe_sqr(&x44, &x44); + } + secp256k1_fe_mul(&x44, &x44, &x22); + + x88 = x44; + for (j=0; j<44; j++) { + secp256k1_fe_sqr(&x88, &x88); + } + secp256k1_fe_mul(&x88, &x88, &x44); + + x176 = x88; + for (j=0; j<88; j++) { + secp256k1_fe_sqr(&x176, &x176); + } + secp256k1_fe_mul(&x176, &x176, &x88); + + x220 = x176; + for (j=0; j<44; j++) { + secp256k1_fe_sqr(&x220, &x220); + } + secp256k1_fe_mul(&x220, &x220, &x44); + + x223 = x220; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x223, &x223); + } + secp256k1_fe_mul(&x223, &x223, &x3); + + /* The final result is then assembled using a sliding window over the blocks. */ + + t1 = x223; + for (j=0; j<23; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, &x22); + for (j=0; j<6; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, &x2); + secp256k1_fe_sqr(&t1, &t1); + secp256k1_fe_sqr(r, &t1); + + /* Check that a square root was actually calculated */ + + secp256k1_fe_sqr(&t1, r); + return secp256k1_fe_equal(&t1, a); +} + +static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) { + secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1; + int j; + + /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in + * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block: + * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223] + */ + + secp256k1_fe_sqr(&x2, a); + secp256k1_fe_mul(&x2, &x2, a); + + secp256k1_fe_sqr(&x3, &x2); + secp256k1_fe_mul(&x3, &x3, a); + + x6 = x3; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x6, &x6); + } + secp256k1_fe_mul(&x6, &x6, &x3); + + x9 = x6; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x9, &x9); + } + secp256k1_fe_mul(&x9, &x9, &x3); + + x11 = x9; + for (j=0; j<2; j++) { + secp256k1_fe_sqr(&x11, &x11); + } + secp256k1_fe_mul(&x11, &x11, &x2); + + x22 = x11; + for (j=0; j<11; j++) { + secp256k1_fe_sqr(&x22, &x22); + } + secp256k1_fe_mul(&x22, &x22, &x11); + + x44 = x22; + for (j=0; j<22; j++) { + secp256k1_fe_sqr(&x44, &x44); + } + secp256k1_fe_mul(&x44, &x44, &x22); + + x88 = x44; + for (j=0; j<44; j++) { + secp256k1_fe_sqr(&x88, &x88); + } + secp256k1_fe_mul(&x88, &x88, &x44); + + x176 = x88; + for (j=0; j<88; j++) { + secp256k1_fe_sqr(&x176, &x176); + } + secp256k1_fe_mul(&x176, &x176, &x88); + + x220 = x176; + for (j=0; j<44; j++) { + secp256k1_fe_sqr(&x220, &x220); + } + secp256k1_fe_mul(&x220, &x220, &x44); + + x223 = x220; + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&x223, &x223); + } + secp256k1_fe_mul(&x223, &x223, &x3); + + /* The final result is then assembled using a sliding window over the blocks. */ + + t1 = x223; + for (j=0; j<23; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, &x22); + for (j=0; j<5; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, a); + for (j=0; j<3; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(&t1, &t1, &x2); + for (j=0; j<2; j++) { + secp256k1_fe_sqr(&t1, &t1); + } + secp256k1_fe_mul(r, a, &t1); +} + +static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) { +#if defined(USE_FIELD_INV_BUILTIN) + secp256k1_fe_inv(r, a); +#elif defined(USE_FIELD_INV_NUM) + secp256k1_num n, m; + static const secp256k1_fe negone = SECP256K1_FE_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xFFFFFC2EUL + ); + /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ + static const unsigned char prime[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F + }; + unsigned char b[32]; + int res; + secp256k1_fe c = *a; + secp256k1_fe_normalize_var(&c); + secp256k1_fe_get_b32(b, &c); + secp256k1_num_set_bin(&n, b, 32); + secp256k1_num_set_bin(&m, prime, 32); + secp256k1_num_mod_inverse(&n, &n, &m); + secp256k1_num_get_bin(b, 32, &n); + res = secp256k1_fe_set_b32(r, b); + (void)res; + VERIFY_CHECK(res); + /* Verify the result is the (unique) valid inverse using non-GMP code. */ + secp256k1_fe_mul(&c, &c, r); + secp256k1_fe_add(&c, &negone); + CHECK(secp256k1_fe_normalizes_to_zero_var(&c)); +#else +#error "Please select field inverse implementation" +#endif +} + +static void secp256k1_fe_inv_all_var(secp256k1_fe *r, const secp256k1_fe *a, size_t len) { + secp256k1_fe u; + size_t i; + if (len < 1) { + return; + } + + VERIFY_CHECK((r + len <= a) || (a + len <= r)); + + r[0] = a[0]; + + i = 0; + while (++i < len) { + secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]); + } + + secp256k1_fe_inv_var(&u, &r[--i]); + + while (i > 0) { + size_t j = i--; + secp256k1_fe_mul(&r[j], &r[i], &u); + secp256k1_fe_mul(&u, &u, &a[j]); + } + + r[0] = u; +} + +static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) { +#ifndef USE_NUM_NONE + unsigned char b[32]; + secp256k1_num n; + secp256k1_num m; + /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ + static const unsigned char prime[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F + }; + + secp256k1_fe c = *a; + secp256k1_fe_normalize_var(&c); + secp256k1_fe_get_b32(b, &c); + secp256k1_num_set_bin(&n, b, 32); + secp256k1_num_set_bin(&m, prime, 32); + return secp256k1_num_jacobi(&n, &m) >= 0; +#else + secp256k1_fe r; + return secp256k1_fe_sqrt(&r, a); +#endif +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c new file mode 100644 index 00000000..1835fd49 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/gen_context.c @@ -0,0 +1,74 @@ +/********************************************************************** + * Copyright (c) 2013, 2014, 2015 Thomas Daede, Cory Fields * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#define USE_BASIC_CONFIG 1 + +#include "basic-config.h" +#include "include/secp256k1.h" +#include "field_impl.h" +#include "scalar_impl.h" +#include "group_impl.h" +#include "ecmult_gen_impl.h" + +static void default_error_callback_fn(const char* str, void* data) { + (void)data; + fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); + abort(); +} + +static const secp256k1_callback default_error_callback = { + default_error_callback_fn, + NULL +}; + +int main(int argc, char **argv) { + secp256k1_ecmult_gen_context ctx; + int inner; + int outer; + FILE* fp; + + (void)argc; + (void)argv; + + fp = fopen("src/ecmult_static_context.h","w"); + if (fp == NULL) { + fprintf(stderr, "Could not open src/ecmult_static_context.h for writing!\n"); + return -1; + } + + fprintf(fp, "#ifndef _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); + fprintf(fp, "#define _SECP256K1_ECMULT_STATIC_CONTEXT_\n"); + fprintf(fp, "#include \"group.h\"\n"); + fprintf(fp, "#define SC SECP256K1_GE_STORAGE_CONST\n"); + fprintf(fp, "static const secp256k1_ge_storage secp256k1_ecmult_static_context[64][16] = {\n"); + + secp256k1_ecmult_gen_context_init(&ctx); + secp256k1_ecmult_gen_context_build(&ctx, &default_error_callback); + for(outer = 0; outer != 64; outer++) { + fprintf(fp,"{\n"); + for(inner = 0; inner != 16; inner++) { + fprintf(fp," SC(%uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu, %uu)", SECP256K1_GE_STORAGE_CONST_GET((*ctx.prec)[outer][inner])); + if (inner != 15) { + fprintf(fp,",\n"); + } else { + fprintf(fp,"\n"); + } + } + if (outer != 63) { + fprintf(fp,"},\n"); + } else { + fprintf(fp,"}\n"); + } + } + fprintf(fp,"};\n"); + secp256k1_ecmult_gen_context_clear(&ctx); + + fprintf(fp, "#undef SC\n"); + fprintf(fp, "#endif\n"); + fclose(fp); + + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h new file mode 100644 index 00000000..4957b248 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group.h @@ -0,0 +1,144 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_GROUP_ +#define _SECP256K1_GROUP_ + +#include "num.h" +#include "field.h" + +/** A group element of the secp256k1 curve, in affine coordinates. */ +typedef struct { + secp256k1_fe x; + secp256k1_fe y; + int infinity; /* whether this represents the point at infinity */ +} secp256k1_ge; + +#define SECP256K1_GE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), 0} +#define SECP256K1_GE_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} + +/** A group element of the secp256k1 curve, in jacobian coordinates. */ +typedef struct { + secp256k1_fe x; /* actual X: x/z^2 */ + secp256k1_fe y; /* actual Y: y/z^3 */ + secp256k1_fe z; + int infinity; /* whether this represents the point at infinity */ +} secp256k1_gej; + +#define SECP256K1_GEJ_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_CONST((i),(j),(k),(l),(m),(n),(o),(p)), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1), 0} +#define SECP256K1_GEJ_CONST_INFINITY {SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 0), 1} + +typedef struct { + secp256k1_fe_storage x; + secp256k1_fe_storage y; +} secp256k1_ge_storage; + +#define SECP256K1_GE_STORAGE_CONST(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {SECP256K1_FE_STORAGE_CONST((a),(b),(c),(d),(e),(f),(g),(h)), SECP256K1_FE_STORAGE_CONST((i),(j),(k),(l),(m),(n),(o),(p))} + +#define SECP256K1_GE_STORAGE_CONST_GET(t) SECP256K1_FE_STORAGE_CONST_GET(t.x), SECP256K1_FE_STORAGE_CONST_GET(t.y) + +/** Set a group element equal to the point with given X and Y coordinates */ +static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y); + +/** Set a group element (affine) equal to the point with the given X coordinate + * and a Y coordinate that is a quadratic residue modulo p. The return value + * is true iff a coordinate with the given X coordinate exists. + */ +static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x); + +/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness + * for Y. Return value indicates whether the result is valid. */ +static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd); + +/** Check whether a group element is the point at infinity. */ +static int secp256k1_ge_is_infinity(const secp256k1_ge *a); + +/** Check whether a group element is valid (i.e., on the curve). */ +static int secp256k1_ge_is_valid_var(const secp256k1_ge *a); + +static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a); + +/** Set a group element equal to another which is given in jacobian coordinates */ +static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a); + +/** Set a batch of group elements equal to the inputs given in jacobian coordinates */ +static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb); + +/** Set a batch of group elements equal to the inputs given in jacobian + * coordinates (with known z-ratios). zr must contain the known z-ratios such + * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. */ +static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len); + +/** Bring a batch inputs given in jacobian coordinates (with known z-ratios) to + * the same global z "denominator". zr must contain the known z-ratios such + * that mul(a[i].z, zr[i+1]) == a[i+1].z. zr[0] is ignored. The x and y + * coordinates of the result are stored in r, the common z coordinate is + * stored in globalz. */ +static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr); + +/** Set a group element (jacobian) equal to the point at infinity. */ +static void secp256k1_gej_set_infinity(secp256k1_gej *r); + +/** Set a group element (jacobian) equal to another which is given in affine coordinates. */ +static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a); + +/** Compare the X coordinate of a group element (jacobian). */ +static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a); + +/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */ +static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a); + +/** Check whether a group element is the point at infinity. */ +static int secp256k1_gej_is_infinity(const secp256k1_gej *a); + +/** Check whether a group element's y coordinate is a quadratic residue. */ +static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a); + +/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). + * a may not be zero. Constant time. */ +static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); + +/** Set r equal to the double of a. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0). */ +static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr); + +/** Set r equal to the sum of a and b. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ +static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr); + +/** Set r equal to the sum of a and b (with b given in affine coordinates, and not infinity). */ +static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b); + +/** Set r equal to the sum of a and b (with b given in affine coordinates). This is more efficient + than secp256k1_gej_add_var. It is identical to secp256k1_gej_add_ge but without constant-time + guarantee, and b is allowed to be infinity. If rzr is non-NULL, r->z = a->z * *rzr (a cannot be infinity in that case). */ +static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr); + +/** Set r equal to the sum of a and b (with the inverse of b's Z coordinate passed as bzinv). */ +static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv); + +#ifdef USE_ENDOMORPHISM +/** Set r to be equal to lambda times a, where lambda is chosen in a way such that this is very fast. */ +static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a); +#endif + +/** Clear a secp256k1_gej to prevent leaking sensitive information. */ +static void secp256k1_gej_clear(secp256k1_gej *r); + +/** Clear a secp256k1_ge to prevent leaking sensitive information. */ +static void secp256k1_ge_clear(secp256k1_ge *r); + +/** Convert a group element to the storage type. */ +static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a); + +/** Convert a group element back from the storage type. */ +static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a); + +/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. */ +static void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag); + +/** Rescale a jacobian point by b which must be non-zero. Constant-time. */ +static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h new file mode 100644 index 00000000..7d723532 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/group_impl.h @@ -0,0 +1,700 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_GROUP_IMPL_H_ +#define _SECP256K1_GROUP_IMPL_H_ + +#include "num.h" +#include "field.h" +#include "group.h" + +/* These points can be generated in sage as follows: + * + * 0. Setup a worksheet with the following parameters. + * b = 4 # whatever CURVE_B will be set to + * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) + * C = EllipticCurve ([F (0), F (b)]) + * + * 1. Determine all the small orders available to you. (If there are + * no satisfactory ones, go back and change b.) + * print C.order().factor(limit=1000) + * + * 2. Choose an order as one of the prime factors listed in the above step. + * (You can also multiply some to get a composite order, though the + * tests will crash trying to invert scalars during signing.) We take a + * random point and scale it to drop its order to the desired value. + * There is some probability this won't work; just try again. + * order = 199 + * P = C.random_point() + * P = (int(P.order()) / int(order)) * P + * assert(P.order() == order) + * + * 3. Print the values. You'll need to use a vim macro or something to + * split the hex output into 4-byte chunks. + * print "%x %x" % P.xy() + */ +#if defined(EXHAUSTIVE_TEST_ORDER) +# if EXHAUSTIVE_TEST_ORDER == 199 +const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( + 0xFA7CC9A7, 0x0737F2DB, 0xA749DD39, 0x2B4FB069, + 0x3B017A7D, 0xA808C2F1, 0xFB12940C, 0x9EA66C18, + 0x78AC123A, 0x5ED8AEF3, 0x8732BC91, 0x1F3A2868, + 0x48DF246C, 0x808DAE72, 0xCFE52572, 0x7F0501ED +); + +const int CURVE_B = 4; +# elif EXHAUSTIVE_TEST_ORDER == 13 +const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( + 0xedc60018, 0xa51a786b, 0x2ea91f4d, 0x4c9416c0, + 0x9de54c3b, 0xa1316554, 0x6cf4345c, 0x7277ef15, + 0x54cb1b6b, 0xdc8c1273, 0x087844ea, 0x43f4603e, + 0x0eaf9a43, 0xf6effe55, 0x939f806d, 0x37adf8ac +); +const int CURVE_B = 2; +# else +# error No known generator for the specified exhaustive test group order. +# endif +#else +/** Generator for secp256k1, value 'g' defined in + * "Standards for Efficient Cryptography" (SEC2) 2.7.1. + */ +static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_GE_CONST( + 0x79BE667EUL, 0xF9DCBBACUL, 0x55A06295UL, 0xCE870B07UL, + 0x029BFCDBUL, 0x2DCE28D9UL, 0x59F2815BUL, 0x16F81798UL, + 0x483ADA77UL, 0x26A3C465UL, 0x5DA4FBFCUL, 0x0E1108A8UL, + 0xFD17B448UL, 0xA6855419UL, 0x9C47D08FUL, 0xFB10D4B8UL +); + +const int CURVE_B = 7; +#endif + +static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) { + secp256k1_fe zi2; + secp256k1_fe zi3; + secp256k1_fe_sqr(&zi2, zi); + secp256k1_fe_mul(&zi3, &zi2, zi); + secp256k1_fe_mul(&r->x, &a->x, &zi2); + secp256k1_fe_mul(&r->y, &a->y, &zi3); + r->infinity = a->infinity; +} + +static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) { + r->infinity = 0; + r->x = *x; + r->y = *y; +} + +static int secp256k1_ge_is_infinity(const secp256k1_ge *a) { + return a->infinity; +} + +static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) { + *r = *a; + secp256k1_fe_normalize_weak(&r->y); + secp256k1_fe_negate(&r->y, &r->y, 1); +} + +static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) { + secp256k1_fe z2, z3; + r->infinity = a->infinity; + secp256k1_fe_inv(&a->z, &a->z); + secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_mul(&z3, &a->z, &z2); + secp256k1_fe_mul(&a->x, &a->x, &z2); + secp256k1_fe_mul(&a->y, &a->y, &z3); + secp256k1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) { + secp256k1_fe z2, z3; + r->infinity = a->infinity; + if (a->infinity) { + return; + } + secp256k1_fe_inv_var(&a->z, &a->z); + secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_mul(&z3, &a->z, &z2); + secp256k1_fe_mul(&a->x, &a->x, &z2); + secp256k1_fe_mul(&a->y, &a->y, &z3); + secp256k1_fe_set_int(&a->z, 1); + r->x = a->x; + r->y = a->y; +} + +static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len, const secp256k1_callback *cb) { + secp256k1_fe *az; + secp256k1_fe *azi; + size_t i; + size_t count = 0; + az = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * len); + for (i = 0; i < len; i++) { + if (!a[i].infinity) { + az[count++] = a[i].z; + } + } + + azi = (secp256k1_fe *)checked_malloc(cb, sizeof(secp256k1_fe) * count); + secp256k1_fe_inv_all_var(azi, az, count); + free(az); + + count = 0; + for (i = 0; i < len; i++) { + r[i].infinity = a[i].infinity; + if (!a[i].infinity) { + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &azi[count++]); + } + } + free(azi); +} + +static void secp256k1_ge_set_table_gej_var(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zr, size_t len) { + size_t i = len - 1; + secp256k1_fe zi; + + if (len > 0) { + /* Compute the inverse of the last z coordinate, and use it to compute the last affine output. */ + secp256k1_fe_inv(&zi, &a[i].z); + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); + + /* Work out way backwards, using the z-ratios to scale the x/y values. */ + while (i > 0) { + secp256k1_fe_mul(&zi, &zi, &zr[i]); + i--; + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zi); + } + } +} + +static void secp256k1_ge_globalz_set_table_gej(size_t len, secp256k1_ge *r, secp256k1_fe *globalz, const secp256k1_gej *a, const secp256k1_fe *zr) { + size_t i = len - 1; + secp256k1_fe zs; + + if (len > 0) { + /* The z of the final point gives us the "global Z" for the table. */ + r[i].x = a[i].x; + r[i].y = a[i].y; + *globalz = a[i].z; + r[i].infinity = 0; + zs = zr[i]; + + /* Work our way backwards, using the z-ratios to scale the x/y values. */ + while (i > 0) { + if (i != len - 1) { + secp256k1_fe_mul(&zs, &zs, &zr[i]); + } + i--; + secp256k1_ge_set_gej_zinv(&r[i], &a[i], &zs); + } + } +} + +static void secp256k1_gej_set_infinity(secp256k1_gej *r) { + r->infinity = 1; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); + secp256k1_fe_clear(&r->z); +} + +static void secp256k1_gej_clear(secp256k1_gej *r) { + r->infinity = 0; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); + secp256k1_fe_clear(&r->z); +} + +static void secp256k1_ge_clear(secp256k1_ge *r) { + r->infinity = 0; + secp256k1_fe_clear(&r->x); + secp256k1_fe_clear(&r->y); +} + +static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) { + secp256k1_fe x2, x3, c; + r->x = *x; + secp256k1_fe_sqr(&x2, x); + secp256k1_fe_mul(&x3, x, &x2); + r->infinity = 0; + secp256k1_fe_set_int(&c, CURVE_B); + secp256k1_fe_add(&c, &x3); + return secp256k1_fe_sqrt(&r->y, &c); +} + +static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) { + if (!secp256k1_ge_set_xquad(r, x)) { + return 0; + } + secp256k1_fe_normalize_var(&r->y); + if (secp256k1_fe_is_odd(&r->y) != odd) { + secp256k1_fe_negate(&r->y, &r->y, 1); + } + return 1; + +} + +static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + secp256k1_fe_set_int(&r->z, 1); +} + +static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) { + secp256k1_fe r, r2; + VERIFY_CHECK(!a->infinity); + secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x); + r2 = a->x; secp256k1_fe_normalize_weak(&r2); + return secp256k1_fe_equal_var(&r, &r2); +} + +static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) { + r->infinity = a->infinity; + r->x = a->x; + r->y = a->y; + r->z = a->z; + secp256k1_fe_normalize_weak(&r->y); + secp256k1_fe_negate(&r->y, &r->y, 1); +} + +static int secp256k1_gej_is_infinity(const secp256k1_gej *a) { + return a->infinity; +} + +static int secp256k1_gej_is_valid_var(const secp256k1_gej *a) { + secp256k1_fe y2, x3, z2, z6; + if (a->infinity) { + return 0; + } + /** y^2 = x^3 + 7 + * (Y/Z^3)^2 = (X/Z^2)^3 + 7 + * Y^2 / Z^6 = X^3 / Z^6 + 7 + * Y^2 = X^3 + 7*Z^6 + */ + secp256k1_fe_sqr(&y2, &a->y); + secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); + secp256k1_fe_sqr(&z2, &a->z); + secp256k1_fe_sqr(&z6, &z2); secp256k1_fe_mul(&z6, &z6, &z2); + secp256k1_fe_mul_int(&z6, CURVE_B); + secp256k1_fe_add(&x3, &z6); + secp256k1_fe_normalize_weak(&x3); + return secp256k1_fe_equal_var(&y2, &x3); +} + +static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) { + secp256k1_fe y2, x3, c; + if (a->infinity) { + return 0; + } + /* y^2 = x^3 + 7 */ + secp256k1_fe_sqr(&y2, &a->y); + secp256k1_fe_sqr(&x3, &a->x); secp256k1_fe_mul(&x3, &x3, &a->x); + secp256k1_fe_set_int(&c, CURVE_B); + secp256k1_fe_add(&x3, &c); + secp256k1_fe_normalize_weak(&x3); + return secp256k1_fe_equal_var(&y2, &x3); +} + +static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { + /* Operations: 3 mul, 4 sqr, 0 normalize, 12 mul_int/add/negate. + * + * Note that there is an implementation described at + * https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + * which trades a multiply for a square, but in practice this is actually slower, + * mainly because it requires more normalizations. + */ + secp256k1_fe t1,t2,t3,t4; + /** For secp256k1, 2Q is infinity if and only if Q is infinity. This is because if 2Q = infinity, + * Q must equal -Q, or that Q.y == -(Q.y), or Q.y is 0. For a point on y^2 = x^3 + 7 to have + * y=0, x^3 must be -7 mod p. However, -7 has no cube root mod p. + * + * Having said this, if this function receives a point on a sextic twist, e.g. by + * a fault attack, it is possible for y to be 0. This happens for y^2 = x^3 + 6, + * since -6 does have a cube root mod p. For this point, this function will not set + * the infinity flag even though the point doubles to infinity, and the result + * point will be gibberish (z = 0 but infinity = 0). + */ + r->infinity = a->infinity; + if (r->infinity) { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 1); + } + return; + } + + if (rzr != NULL) { + *rzr = a->y; + secp256k1_fe_normalize_weak(rzr); + secp256k1_fe_mul_int(rzr, 2); + } + + secp256k1_fe_mul(&r->z, &a->z, &a->y); + secp256k1_fe_mul_int(&r->z, 2); /* Z' = 2*Y*Z (2) */ + secp256k1_fe_sqr(&t1, &a->x); + secp256k1_fe_mul_int(&t1, 3); /* T1 = 3*X^2 (3) */ + secp256k1_fe_sqr(&t2, &t1); /* T2 = 9*X^4 (1) */ + secp256k1_fe_sqr(&t3, &a->y); + secp256k1_fe_mul_int(&t3, 2); /* T3 = 2*Y^2 (2) */ + secp256k1_fe_sqr(&t4, &t3); + secp256k1_fe_mul_int(&t4, 2); /* T4 = 8*Y^4 (2) */ + secp256k1_fe_mul(&t3, &t3, &a->x); /* T3 = 2*X*Y^2 (1) */ + r->x = t3; + secp256k1_fe_mul_int(&r->x, 4); /* X' = 8*X*Y^2 (4) */ + secp256k1_fe_negate(&r->x, &r->x, 4); /* X' = -8*X*Y^2 (5) */ + secp256k1_fe_add(&r->x, &t2); /* X' = 9*X^4 - 8*X*Y^2 (6) */ + secp256k1_fe_negate(&t2, &t2, 1); /* T2 = -9*X^4 (2) */ + secp256k1_fe_mul_int(&t3, 6); /* T3 = 12*X*Y^2 (6) */ + secp256k1_fe_add(&t3, &t2); /* T3 = 12*X*Y^2 - 9*X^4 (8) */ + secp256k1_fe_mul(&r->y, &t1, &t3); /* Y' = 36*X^3*Y^2 - 27*X^6 (1) */ + secp256k1_fe_negate(&t2, &t4, 2); /* T2 = -8*Y^4 (3) */ + secp256k1_fe_add(&r->y, &t2); /* Y' = 36*X^3*Y^2 - 27*X^6 - 8*Y^4 (4) */ +} + +static SECP256K1_INLINE void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) { + VERIFY_CHECK(!secp256k1_gej_is_infinity(a)); + secp256k1_gej_double_var(r, a, rzr); +} + +static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) { + /* Operations: 12 mul, 4 sqr, 2 normalize, 12 mul_int/add/negate */ + secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + + if (a->infinity) { + VERIFY_CHECK(rzr == NULL); + *r = *b; + return; + } + + if (b->infinity) { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 1); + } + *r = *a; + return; + } + + r->infinity = 0; + secp256k1_fe_sqr(&z22, &b->z); + secp256k1_fe_sqr(&z12, &a->z); + secp256k1_fe_mul(&u1, &a->x, &z22); + secp256k1_fe_mul(&u2, &b->x, &z12); + secp256k1_fe_mul(&s1, &a->y, &z22); secp256k1_fe_mul(&s1, &s1, &b->z); + secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); + secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); + secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); + if (secp256k1_fe_normalizes_to_zero_var(&h)) { + if (secp256k1_fe_normalizes_to_zero_var(&i)) { + secp256k1_gej_double_var(r, a, rzr); + } else { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 0); + } + r->infinity = 1; + } + return; + } + secp256k1_fe_sqr(&i2, &i); + secp256k1_fe_sqr(&h2, &h); + secp256k1_fe_mul(&h3, &h, &h2); + secp256k1_fe_mul(&h, &h, &b->z); + if (rzr != NULL) { + *rzr = h; + } + secp256k1_fe_mul(&r->z, &a->z, &h); + secp256k1_fe_mul(&t, &u1, &h2); + r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); + secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); + secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); + secp256k1_fe_add(&r->y, &h3); +} + +static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) { + /* 8 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ + secp256k1_fe z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + if (a->infinity) { + VERIFY_CHECK(rzr == NULL); + secp256k1_gej_set_ge(r, b); + return; + } + if (b->infinity) { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 1); + } + *r = *a; + return; + } + r->infinity = 0; + + secp256k1_fe_sqr(&z12, &a->z); + u1 = a->x; secp256k1_fe_normalize_weak(&u1); + secp256k1_fe_mul(&u2, &b->x, &z12); + s1 = a->y; secp256k1_fe_normalize_weak(&s1); + secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &a->z); + secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); + secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); + if (secp256k1_fe_normalizes_to_zero_var(&h)) { + if (secp256k1_fe_normalizes_to_zero_var(&i)) { + secp256k1_gej_double_var(r, a, rzr); + } else { + if (rzr != NULL) { + secp256k1_fe_set_int(rzr, 0); + } + r->infinity = 1; + } + return; + } + secp256k1_fe_sqr(&i2, &i); + secp256k1_fe_sqr(&h2, &h); + secp256k1_fe_mul(&h3, &h, &h2); + if (rzr != NULL) { + *rzr = h; + } + secp256k1_fe_mul(&r->z, &a->z, &h); + secp256k1_fe_mul(&t, &u1, &h2); + r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); + secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); + secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); + secp256k1_fe_add(&r->y, &h3); +} + +static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) { + /* 9 mul, 3 sqr, 4 normalize, 12 mul_int/add/negate */ + secp256k1_fe az, z12, u1, u2, s1, s2, h, i, i2, h2, h3, t; + + if (b->infinity) { + *r = *a; + return; + } + if (a->infinity) { + secp256k1_fe bzinv2, bzinv3; + r->infinity = b->infinity; + secp256k1_fe_sqr(&bzinv2, bzinv); + secp256k1_fe_mul(&bzinv3, &bzinv2, bzinv); + secp256k1_fe_mul(&r->x, &b->x, &bzinv2); + secp256k1_fe_mul(&r->y, &b->y, &bzinv3); + secp256k1_fe_set_int(&r->z, 1); + return; + } + r->infinity = 0; + + /** We need to calculate (rx,ry,rz) = (ax,ay,az) + (bx,by,1/bzinv). Due to + * secp256k1's isomorphism we can multiply the Z coordinates on both sides + * by bzinv, and get: (rx,ry,rz*bzinv) = (ax,ay,az*bzinv) + (bx,by,1). + * This means that (rx,ry,rz) can be calculated as + * (ax,ay,az*bzinv) + (bx,by,1), when not applying the bzinv factor to rz. + * The variable az below holds the modified Z coordinate for a, which is used + * for the computation of rx and ry, but not for rz. + */ + secp256k1_fe_mul(&az, &a->z, bzinv); + + secp256k1_fe_sqr(&z12, &az); + u1 = a->x; secp256k1_fe_normalize_weak(&u1); + secp256k1_fe_mul(&u2, &b->x, &z12); + s1 = a->y; secp256k1_fe_normalize_weak(&s1); + secp256k1_fe_mul(&s2, &b->y, &z12); secp256k1_fe_mul(&s2, &s2, &az); + secp256k1_fe_negate(&h, &u1, 1); secp256k1_fe_add(&h, &u2); + secp256k1_fe_negate(&i, &s1, 1); secp256k1_fe_add(&i, &s2); + if (secp256k1_fe_normalizes_to_zero_var(&h)) { + if (secp256k1_fe_normalizes_to_zero_var(&i)) { + secp256k1_gej_double_var(r, a, NULL); + } else { + r->infinity = 1; + } + return; + } + secp256k1_fe_sqr(&i2, &i); + secp256k1_fe_sqr(&h2, &h); + secp256k1_fe_mul(&h3, &h, &h2); + r->z = a->z; secp256k1_fe_mul(&r->z, &r->z, &h); + secp256k1_fe_mul(&t, &u1, &h2); + r->x = t; secp256k1_fe_mul_int(&r->x, 2); secp256k1_fe_add(&r->x, &h3); secp256k1_fe_negate(&r->x, &r->x, 3); secp256k1_fe_add(&r->x, &i2); + secp256k1_fe_negate(&r->y, &r->x, 5); secp256k1_fe_add(&r->y, &t); secp256k1_fe_mul(&r->y, &r->y, &i); + secp256k1_fe_mul(&h3, &h3, &s1); secp256k1_fe_negate(&h3, &h3, 1); + secp256k1_fe_add(&r->y, &h3); +} + + +static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b) { + /* Operations: 7 mul, 5 sqr, 4 normalize, 21 mul_int/add/negate/cmov */ + static const secp256k1_fe fe_1 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr; + secp256k1_fe m_alt, rr_alt; + int infinity, degenerate; + VERIFY_CHECK(!b->infinity); + VERIFY_CHECK(a->infinity == 0 || a->infinity == 1); + + /** In: + * Eric Brier and Marc Joye, Weierstrass Elliptic Curves and Side-Channel Attacks. + * In D. Naccache and P. Paillier, Eds., Public Key Cryptography, vol. 2274 of Lecture Notes in Computer Science, pages 335-345. Springer-Verlag, 2002. + * we find as solution for a unified addition/doubling formula: + * lambda = ((x1 + x2)^2 - x1 * x2 + a) / (y1 + y2), with a = 0 for secp256k1's curve equation. + * x3 = lambda^2 - (x1 + x2) + * 2*y3 = lambda * (x1 + x2 - 2 * x3) - (y1 + y2). + * + * Substituting x_i = Xi / Zi^2 and yi = Yi / Zi^3, for i=1,2,3, gives: + * U1 = X1*Z2^2, U2 = X2*Z1^2 + * S1 = Y1*Z2^3, S2 = Y2*Z1^3 + * Z = Z1*Z2 + * T = U1+U2 + * M = S1+S2 + * Q = T*M^2 + * R = T^2-U1*U2 + * X3 = 4*(R^2-Q) + * Y3 = 4*(R*(3*Q-2*R^2)-M^4) + * Z3 = 2*M*Z + * (Note that the paper uses xi = Xi / Zi and yi = Yi / Zi instead.) + * + * This formula has the benefit of being the same for both addition + * of distinct points and doubling. However, it breaks down in the + * case that either point is infinity, or that y1 = -y2. We handle + * these cases in the following ways: + * + * - If b is infinity we simply bail by means of a VERIFY_CHECK. + * + * - If a is infinity, we detect this, and at the end of the + * computation replace the result (which will be meaningless, + * but we compute to be constant-time) with b.x : b.y : 1. + * + * - If a = -b, we have y1 = -y2, which is a degenerate case. + * But here the answer is infinity, so we simply set the + * infinity flag of the result, overriding the computed values + * without even needing to cmov. + * + * - If y1 = -y2 but x1 != x2, which does occur thanks to certain + * properties of our curve (specifically, 1 has nontrivial cube + * roots in our field, and the curve equation has no x coefficient) + * then the answer is not infinity but also not given by the above + * equation. In this case, we cmov in place an alternate expression + * for lambda. Specifically (y1 - y2)/(x1 - x2). Where both these + * expressions for lambda are defined, they are equal, and can be + * obtained from each other by multiplication by (y1 + y2)/(y1 + y2) + * then substitution of x^3 + 7 for y^2 (using the curve equation). + * For all pairs of nonzero points (a, b) at least one is defined, + * so this covers everything. + */ + + secp256k1_fe_sqr(&zz, &a->z); /* z = Z1^2 */ + u1 = a->x; secp256k1_fe_normalize_weak(&u1); /* u1 = U1 = X1*Z2^2 (1) */ + secp256k1_fe_mul(&u2, &b->x, &zz); /* u2 = U2 = X2*Z1^2 (1) */ + s1 = a->y; secp256k1_fe_normalize_weak(&s1); /* s1 = S1 = Y1*Z2^3 (1) */ + secp256k1_fe_mul(&s2, &b->y, &zz); /* s2 = Y2*Z1^2 (1) */ + secp256k1_fe_mul(&s2, &s2, &a->z); /* s2 = S2 = Y2*Z1^3 (1) */ + t = u1; secp256k1_fe_add(&t, &u2); /* t = T = U1+U2 (2) */ + m = s1; secp256k1_fe_add(&m, &s2); /* m = M = S1+S2 (2) */ + secp256k1_fe_sqr(&rr, &t); /* rr = T^2 (1) */ + secp256k1_fe_negate(&m_alt, &u2, 1); /* Malt = -X2*Z1^2 */ + secp256k1_fe_mul(&tt, &u1, &m_alt); /* tt = -U1*U2 (2) */ + secp256k1_fe_add(&rr, &tt); /* rr = R = T^2-U1*U2 (3) */ + /** If lambda = R/M = 0/0 we have a problem (except in the "trivial" + * case that Z = z1z2 = 0, and this is special-cased later on). */ + degenerate = secp256k1_fe_normalizes_to_zero(&m) & + secp256k1_fe_normalizes_to_zero(&rr); + /* This only occurs when y1 == -y2 and x1^3 == x2^3, but x1 != x2. + * This means either x1 == beta*x2 or beta*x1 == x2, where beta is + * a nontrivial cube root of one. In either case, an alternate + * non-indeterminate expression for lambda is (y1 - y2)/(x1 - x2), + * so we set R/M equal to this. */ + rr_alt = s1; + secp256k1_fe_mul_int(&rr_alt, 2); /* rr = Y1*Z2^3 - Y2*Z1^3 (2) */ + secp256k1_fe_add(&m_alt, &u1); /* Malt = X1*Z2^2 - X2*Z1^2 */ + + secp256k1_fe_cmov(&rr_alt, &rr, !degenerate); + secp256k1_fe_cmov(&m_alt, &m, !degenerate); + /* Now Ralt / Malt = lambda and is guaranteed not to be 0/0. + * From here on out Ralt and Malt represent the numerator + * and denominator of lambda; R and M represent the explicit + * expressions x1^2 + x2^2 + x1x2 and y1 + y2. */ + secp256k1_fe_sqr(&n, &m_alt); /* n = Malt^2 (1) */ + secp256k1_fe_mul(&q, &n, &t); /* q = Q = T*Malt^2 (1) */ + /* These two lines use the observation that either M == Malt or M == 0, + * so M^3 * Malt is either Malt^4 (which is computed by squaring), or + * zero (which is "computed" by cmov). So the cost is one squaring + * versus two multiplications. */ + secp256k1_fe_sqr(&n, &n); + secp256k1_fe_cmov(&n, &m, degenerate); /* n = M^3 * Malt (2) */ + secp256k1_fe_sqr(&t, &rr_alt); /* t = Ralt^2 (1) */ + secp256k1_fe_mul(&r->z, &a->z, &m_alt); /* r->z = Malt*Z (1) */ + infinity = secp256k1_fe_normalizes_to_zero(&r->z) * (1 - a->infinity); + secp256k1_fe_mul_int(&r->z, 2); /* r->z = Z3 = 2*Malt*Z (2) */ + secp256k1_fe_negate(&q, &q, 1); /* q = -Q (2) */ + secp256k1_fe_add(&t, &q); /* t = Ralt^2-Q (3) */ + secp256k1_fe_normalize_weak(&t); + r->x = t; /* r->x = Ralt^2-Q (1) */ + secp256k1_fe_mul_int(&t, 2); /* t = 2*x3 (2) */ + secp256k1_fe_add(&t, &q); /* t = 2*x3 - Q: (4) */ + secp256k1_fe_mul(&t, &t, &rr_alt); /* t = Ralt*(2*x3 - Q) (1) */ + secp256k1_fe_add(&t, &n); /* t = Ralt*(2*x3 - Q) + M^3*Malt (3) */ + secp256k1_fe_negate(&r->y, &t, 3); /* r->y = Ralt*(Q - 2x3) - M^3*Malt (4) */ + secp256k1_fe_normalize_weak(&r->y); + secp256k1_fe_mul_int(&r->x, 4); /* r->x = X3 = 4*(Ralt^2-Q) */ + secp256k1_fe_mul_int(&r->y, 4); /* r->y = Y3 = 4*Ralt*(Q - 2x3) - 4*M^3*Malt (4) */ + + /** In case a->infinity == 1, replace r with (b->x, b->y, 1). */ + secp256k1_fe_cmov(&r->x, &b->x, a->infinity); + secp256k1_fe_cmov(&r->y, &b->y, a->infinity); + secp256k1_fe_cmov(&r->z, &fe_1, a->infinity); + r->infinity = infinity; +} + +static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) { + /* Operations: 4 mul, 1 sqr */ + secp256k1_fe zz; + VERIFY_CHECK(!secp256k1_fe_is_zero(s)); + secp256k1_fe_sqr(&zz, s); + secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */ + secp256k1_fe_mul(&r->y, &r->y, &zz); + secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */ + secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */ +} + +static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) { + secp256k1_fe x, y; + VERIFY_CHECK(!a->infinity); + x = a->x; + secp256k1_fe_normalize(&x); + y = a->y; + secp256k1_fe_normalize(&y); + secp256k1_fe_to_storage(&r->x, &x); + secp256k1_fe_to_storage(&r->y, &y); +} + +static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storage *a) { + secp256k1_fe_from_storage(&r->x, &a->x); + secp256k1_fe_from_storage(&r->y, &a->y); + r->infinity = 0; +} + +static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) { + secp256k1_fe_storage_cmov(&r->x, &a->x, flag); + secp256k1_fe_storage_cmov(&r->y, &a->y, flag); +} + +#ifdef USE_ENDOMORPHISM +static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) { + static const secp256k1_fe beta = SECP256K1_FE_CONST( + 0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul, + 0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul + ); + *r = *a; + secp256k1_fe_mul(&r->x, &r->x, &beta); +} +#endif + +static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) { + secp256k1_fe yz; + + if (a->infinity) { + return 0; + } + + /* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as + * that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z + is */ + secp256k1_fe_mul(&yz, &a->y, &a->z); + return secp256k1_fe_is_quad_var(&yz); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h new file mode 100644 index 00000000..fca98cab --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash.h @@ -0,0 +1,41 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_HASH_ +#define _SECP256K1_HASH_ + +#include +#include + +typedef struct { + uint32_t s[8]; + uint32_t buf[16]; /* In big endian */ + size_t bytes; +} secp256k1_sha256_t; + +static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash); +static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t size); +static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32); + +typedef struct { + secp256k1_sha256_t inner, outer; +} secp256k1_hmac_sha256_t; + +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t size); +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size); +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32); + +typedef struct { + unsigned char v[32]; + unsigned char k[32]; + int retry; +} secp256k1_rfc6979_hmac_sha256_t; + +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen); +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen); +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h new file mode 100644 index 00000000..b47e65f8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/hash_impl.h @@ -0,0 +1,281 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_HASH_IMPL_H_ +#define _SECP256K1_HASH_IMPL_H_ + +#include "hash.h" + +#include +#include +#include + +#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) +#define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) +#define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) +#define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) + +#define Round(a,b,c,d,e,f,g,h,k,w) do { \ + uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ + uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ + (d) += t1; \ + (h) = t1 + t2; \ +} while(0) + +#ifdef WORDS_BIGENDIAN +#define BE32(x) (x) +#else +#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) +#endif + +static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) { + hash->s[0] = 0x6a09e667ul; + hash->s[1] = 0xbb67ae85ul; + hash->s[2] = 0x3c6ef372ul; + hash->s[3] = 0xa54ff53aul; + hash->s[4] = 0x510e527ful; + hash->s[5] = 0x9b05688cul; + hash->s[6] = 0x1f83d9abul; + hash->s[7] = 0x5be0cd19ul; + hash->bytes = 0; +} + +/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ +static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { + uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7]; + uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; + + Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0])); + Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1])); + Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2])); + Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3])); + Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4])); + Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5])); + Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6])); + Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7])); + Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8])); + Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9])); + Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10])); + Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11])); + Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12])); + Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13])); + Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14])); + Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15])); + + Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); + + Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); + Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); + Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); + Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); + Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); + Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); + Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); + Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); + Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); + Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); + Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); + Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); + Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); + Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); + Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); + Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); + + s[0] += a; + s[1] += b; + s[2] += c; + s[3] += d; + s[4] += e; + s[5] += f; + s[6] += g; + s[7] += h; +} + +static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) { + size_t bufsize = hash->bytes & 0x3F; + hash->bytes += len; + while (bufsize + len >= 64) { + /* Fill the buffer, and process it. */ + memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize); + data += 64 - bufsize; + len -= 64 - bufsize; + secp256k1_sha256_transform(hash->s, hash->buf); + bufsize = 0; + } + if (len) { + /* Fill the buffer with what remains. */ + memcpy(((unsigned char*)hash->buf) + bufsize, data, len); + } +} + +static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) { + static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint32_t sizedesc[2]; + uint32_t out[8]; + int i = 0; + sizedesc[0] = BE32(hash->bytes >> 29); + sizedesc[1] = BE32(hash->bytes << 3); + secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); + secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8); + for (i = 0; i < 8; i++) { + out[i] = BE32(hash->s[i]); + hash->s[i] = 0; + } + memcpy(out32, (const unsigned char*)out, 32); +} + +static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) { + int n; + unsigned char rkey[64]; + if (keylen <= 64) { + memcpy(rkey, key, keylen); + memset(rkey + keylen, 0, 64 - keylen); + } else { + secp256k1_sha256_t sha256; + secp256k1_sha256_initialize(&sha256); + secp256k1_sha256_write(&sha256, key, keylen); + secp256k1_sha256_finalize(&sha256, rkey); + memset(rkey + 32, 0, 32); + } + + secp256k1_sha256_initialize(&hash->outer); + for (n = 0; n < 64; n++) { + rkey[n] ^= 0x5c; + } + secp256k1_sha256_write(&hash->outer, rkey, 64); + + secp256k1_sha256_initialize(&hash->inner); + for (n = 0; n < 64; n++) { + rkey[n] ^= 0x5c ^ 0x36; + } + secp256k1_sha256_write(&hash->inner, rkey, 64); + memset(rkey, 0, 64); +} + +static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256_t *hash, const unsigned char *data, size_t size) { + secp256k1_sha256_write(&hash->inner, data, size); +} + +static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256_t *hash, unsigned char *out32) { + unsigned char temp[32]; + secp256k1_sha256_finalize(&hash->inner, temp); + secp256k1_sha256_write(&hash->outer, temp, 32); + memset(temp, 0, 32); + secp256k1_sha256_finalize(&hash->outer, out32); +} + + +static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256_t *rng, const unsigned char *key, size_t keylen) { + secp256k1_hmac_sha256_t hmac; + static const unsigned char zero[1] = {0x00}; + static const unsigned char one[1] = {0x01}; + + memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */ + memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ + + /* RFC6979 3.2.d. */ + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, zero, 1); + secp256k1_hmac_sha256_write(&hmac, key, keylen); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + + /* RFC6979 3.2.f. */ + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, one, 1); + secp256k1_hmac_sha256_write(&hmac, key, keylen); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + rng->retry = 0; +} + +static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256_t *rng, unsigned char *out, size_t outlen) { + /* RFC6979 3.2.h. */ + static const unsigned char zero[1] = {0x00}; + if (rng->retry) { + secp256k1_hmac_sha256_t hmac; + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_write(&hmac, zero, 1); + secp256k1_hmac_sha256_finalize(&hmac, rng->k); + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + } + + while (outlen > 0) { + secp256k1_hmac_sha256_t hmac; + int now = outlen; + secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); + secp256k1_hmac_sha256_write(&hmac, rng->v, 32); + secp256k1_hmac_sha256_finalize(&hmac, rng->v); + if (now > 32) { + now = 32; + } + memcpy(out, rng->v, now); + out += now; + outlen -= now; + } + + rng->retry = 1; +} + +static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256_t *rng) { + memset(rng->k, 0, 32); + memset(rng->v, 0, 32); + rng->retry = 0; +} + +#undef BE32 +#undef Round +#undef sigma1 +#undef sigma0 +#undef Sigma1 +#undef Sigma0 +#undef Maj +#undef Ch + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java new file mode 100644 index 00000000..1c67802f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1.java @@ -0,0 +1,446 @@ +/* + * Copyright 2013 Google Inc. + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoin; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import java.math.BigInteger; +import com.google.common.base.Preconditions; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import static org.bitcoin.NativeSecp256k1Util.*; + +/** + *

This class holds native methods to handle ECDSA verification.

+ * + *

You can find an example library that can be used for this at https://github.com/bitcoin/secp256k1

+ * + *

To build secp256k1 for use with bitcoinj, run + * `./configure --enable-jni --enable-experimental --enable-module-ecdh` + * and `make` then copy `.libs/libsecp256k1.so` to your system library path + * or point the JVM to the folder containing it with -Djava.library.path + *

+ */ +public class NativeSecp256k1 { + + private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + private static final Lock r = rwl.readLock(); + private static final Lock w = rwl.writeLock(); + private static ThreadLocal nativeECDSABuffer = new ThreadLocal(); + /** + * Verifies the given secp256k1 signature in native code. + * Calling when enabled == false is undefined (probably library not loaded) + * + * @param data The data which was signed, must be exactly 32 bytes + * @param signature The signature + * @param pub The public key which did the signing + */ + public static boolean verify(byte[] data, byte[] signature, byte[] pub) throws AssertFailException{ + Preconditions.checkArgument(data.length == 32 && signature.length <= 520 && pub.length <= 520); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 520) { + byteBuff = ByteBuffer.allocateDirect(520); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(signature); + byteBuff.put(pub); + + byte[][] retByteArray; + + r.lock(); + try { + return secp256k1_ecdsa_verify(byteBuff, Secp256k1Context.getContext(), signature.length, pub.length) == 1; + } finally { + r.unlock(); + } + } + + /** + * libsecp256k1 Create an ECDSA signature. + * + * @param data Message hash, 32 bytes + * @param key Secret key, 32 bytes + * + * Return values + * @param sig byte array of signature + */ + public static byte[] sign(byte[] data, byte[] sec) throws AssertFailException{ + Preconditions.checkArgument(data.length == 32 && sec.length <= 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 32 + 32) { + byteBuff = ByteBuffer.allocateDirect(32 + 32); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(data); + byteBuff.put(sec); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = secp256k1_ecdsa_sign(byteBuff, Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] sigArr = retByteArray[0]; + int sigLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(sigArr.length, sigLen, "Got bad signature length."); + + return retVal == 0 ? new byte[0] : sigArr; + } + + /** + * libsecp256k1 Seckey Verify - returns 1 if valid, 0 if invalid + * + * @param seckey ECDSA Secret key, 32 bytes + */ + public static boolean secKeyVerify(byte[] seckey) { + Preconditions.checkArgument(seckey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seckey.length) { + byteBuff = ByteBuffer.allocateDirect(seckey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + + r.lock(); + try { + return secp256k1_ec_seckey_verify(byteBuff,Secp256k1Context.getContext()) == 1; + } finally { + r.unlock(); + } + } + + + /** + * libsecp256k1 Compute Pubkey - computes public key from secret key + * + * @param seckey ECDSA Secret key, 32 bytes + * + * Return values + * @param pubkey ECDSA Public key, 33 or 65 bytes + */ + //TODO add a 'compressed' arg + public static byte[] computePubkey(byte[] seckey) throws AssertFailException{ + Preconditions.checkArgument(seckey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seckey.length) { + byteBuff = ByteBuffer.allocateDirect(seckey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + + byte[][] retByteArray; + + r.lock(); + try { + retByteArray = secp256k1_ec_pubkey_create(byteBuff, Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + int pubLen = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + return retVal == 0 ? new byte[0]: pubArr; + } + + /** + * libsecp256k1 Cleanup - This destroys the secp256k1 context object + * This should be called at the end of the program for proper cleanup of the context. + */ + public static synchronized void cleanup() { + w.lock(); + try { + secp256k1_destroy_context(Secp256k1Context.getContext()); + } finally { + w.unlock(); + } + } + + public static long cloneContext() { + r.lock(); + try { + return secp256k1_ctx_clone(Secp256k1Context.getContext()); + } finally { r.unlock(); } + } + + /** + * libsecp256k1 PrivKey Tweak-Mul - Tweak privkey by multiplying to it + * + * @param tweak some bytes to tweak with + * @param seckey 32-byte seckey + */ + public static byte[] privKeyTweakMul(byte[] privkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(privkey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(privkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_privkey_tweak_mul(byteBuff,Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] privArr = retByteArray[0]; + + int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(privArr.length, privLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return privArr; + } + + /** + * libsecp256k1 PrivKey Tweak-Add - Tweak privkey by adding to it + * + * @param tweak some bytes to tweak with + * @param seckey 32-byte seckey + */ + public static byte[] privKeyTweakAdd(byte[] privkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(privkey.length == 32); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < privkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(privkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(privkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_privkey_tweak_add(byteBuff,Secp256k1Context.getContext()); + } finally { + r.unlock(); + } + + byte[] privArr = retByteArray[0]; + + int privLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(privArr.length, privLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return privArr; + } + + /** + * libsecp256k1 PubKey Tweak-Add - Tweak pubkey by adding to it + * + * @param tweak some bytes to tweak with + * @param pubkey 32-byte seckey + */ + public static byte[] pubKeyTweakAdd(byte[] pubkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(pubkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_pubkey_tweak_add(byteBuff,Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + + int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return pubArr; + } + + /** + * libsecp256k1 PubKey Tweak-Mul - Tweak pubkey by multiplying to it + * + * @param tweak some bytes to tweak with + * @param pubkey 32-byte seckey + */ + public static byte[] pubKeyTweakMul(byte[] pubkey, byte[] tweak) throws AssertFailException{ + Preconditions.checkArgument(pubkey.length == 33 || pubkey.length == 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < pubkey.length + tweak.length) { + byteBuff = ByteBuffer.allocateDirect(pubkey.length + tweak.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(pubkey); + byteBuff.put(tweak); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_pubkey_tweak_mul(byteBuff,Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] pubArr = retByteArray[0]; + + int pubLen = (byte) new BigInteger(new byte[] { retByteArray[1][0] }).intValue() & 0xFF; + int retVal = new BigInteger(new byte[] { retByteArray[1][1] }).intValue(); + + assertEquals(pubArr.length, pubLen, "Got bad pubkey length."); + + assertEquals(retVal, 1, "Failed return value check."); + + return pubArr; + } + + /** + * libsecp256k1 create ECDH secret - constant time ECDH calculation + * + * @param seckey byte array of secret key used in exponentiaion + * @param pubkey byte array of public key used in exponentiaion + */ + public static byte[] createECDHSecret(byte[] seckey, byte[] pubkey) throws AssertFailException{ + Preconditions.checkArgument(seckey.length <= 32 && pubkey.length <= 65); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < 32 + pubkey.length) { + byteBuff = ByteBuffer.allocateDirect(32 + pubkey.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seckey); + byteBuff.put(pubkey); + + byte[][] retByteArray; + r.lock(); + try { + retByteArray = secp256k1_ecdh(byteBuff, Secp256k1Context.getContext(), pubkey.length); + } finally { + r.unlock(); + } + + byte[] resArr = retByteArray[0]; + int retVal = new BigInteger(new byte[] { retByteArray[1][0] }).intValue(); + + assertEquals(resArr.length, 32, "Got bad result length."); + assertEquals(retVal, 1, "Failed return value check."); + + return resArr; + } + + /** + * libsecp256k1 randomize - updates the context randomization + * + * @param seed 32-byte random seed + */ + public static synchronized boolean randomize(byte[] seed) throws AssertFailException{ + Preconditions.checkArgument(seed.length == 32 || seed == null); + + ByteBuffer byteBuff = nativeECDSABuffer.get(); + if (byteBuff == null || byteBuff.capacity() < seed.length) { + byteBuff = ByteBuffer.allocateDirect(seed.length); + byteBuff.order(ByteOrder.nativeOrder()); + nativeECDSABuffer.set(byteBuff); + } + byteBuff.rewind(); + byteBuff.put(seed); + + w.lock(); + try { + return secp256k1_context_randomize(byteBuff, Secp256k1Context.getContext()) == 1; + } finally { + w.unlock(); + } + } + + private static native long secp256k1_ctx_clone(long context); + + private static native int secp256k1_context_randomize(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_privkey_tweak_add(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_privkey_tweak_mul(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_pubkey_tweak_add(ByteBuffer byteBuff, long context, int pubLen); + + private static native byte[][] secp256k1_pubkey_tweak_mul(ByteBuffer byteBuff, long context, int pubLen); + + private static native void secp256k1_destroy_context(long context); + + private static native int secp256k1_ecdsa_verify(ByteBuffer byteBuff, long context, int sigLen, int pubLen); + + private static native byte[][] secp256k1_ecdsa_sign(ByteBuffer byteBuff, long context); + + private static native int secp256k1_ec_seckey_verify(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_ec_pubkey_create(ByteBuffer byteBuff, long context); + + private static native byte[][] secp256k1_ec_pubkey_parse(ByteBuffer byteBuff, long context, int inputLen); + + private static native byte[][] secp256k1_ecdh(ByteBuffer byteBuff, long context, int inputLen); + +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java new file mode 100644 index 00000000..c00d0889 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Test.java @@ -0,0 +1,226 @@ +package org.bitcoin; + +import com.google.common.io.BaseEncoding; +import java.util.Arrays; +import java.math.BigInteger; +import javax.xml.bind.DatatypeConverter; +import static org.bitcoin.NativeSecp256k1Util.*; + +/** + * This class holds test cases defined for testing this library. + */ +public class NativeSecp256k1Test { + + //TODO improve comments/add more tests + /** + * This tests verify() for a valid signature + */ + public static void testVerifyPos() throws AssertFailException{ + boolean result = false; + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + result = NativeSecp256k1.verify( data, sig, pub); + assertEquals( result, true , "testVerifyPos"); + } + + /** + * This tests verify() for a non-valid signature + */ + public static void testVerifyNeg() throws AssertFailException{ + boolean result = false; + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A91".toLowerCase()); //sha256hash of "testing" + byte[] sig = BaseEncoding.base16().lowerCase().decode("3044022079BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980220294F14E883B3F525B5367756C2A11EF6CF84B730B36C17CB0C56F0AAB2C98589".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + result = NativeSecp256k1.verify( data, sig, pub); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, false , "testVerifyNeg"); + } + + /** + * This tests secret key verify() for a valid secretkey + */ + public static void testSecKeyVerifyPos() throws AssertFailException{ + boolean result = false; + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + result = NativeSecp256k1.secKeyVerify( sec ); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, true , "testSecKeyVerifyPos"); + } + + /** + * This tests secret key verify() for a invalid secretkey + */ + public static void testSecKeyVerifyNeg() throws AssertFailException{ + boolean result = false; + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + result = NativeSecp256k1.secKeyVerify( sec ); + //System.out.println(" TEST " + new BigInteger(1, resultbytes).toString(16)); + assertEquals( result, false , "testSecKeyVerifyNeg"); + } + + /** + * This tests public key create() for a valid secretkey + */ + public static void testPubKeyCreatePos() throws AssertFailException{ + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( pubkeyString , "04C591A8FF19AC9C4E4E5793673B83123437E975285E7B442F4EE2654DFFCA5E2D2103ED494718C697AC9AEBCFD19612E224DB46661011863ED2FC54E71861E2A6" , "testPubKeyCreatePos"); + } + + /** + * This tests public key create() for a invalid secretkey + */ + public static void testPubKeyCreateNeg() throws AssertFailException{ + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.computePubkey( sec); + String pubkeyString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( pubkeyString, "" , "testPubKeyCreateNeg"); + } + + /** + * This tests sign() for a valid secretkey + */ + public static void testSignPos() throws AssertFailException{ + + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.sign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "30440220182A108E1448DC8F1FB467D06A0F3BB8EA0533584CB954EF8DA112F1D60E39A202201C66F36DA211C087F3AF88B50EDF4F9BDAA6CF5FD6817E74DCA34DB12390C6E9" , "testSignPos"); + } + + /** + * This tests sign() for a invalid secretkey + */ + public static void testSignNeg() throws AssertFailException{ + byte[] data = BaseEncoding.base16().lowerCase().decode("CF80CD8AED482D5D1527D7DC72FCEFF84E6326592848447D2DC0B0E87DFC9A90".toLowerCase()); //sha256hash of "testing" + byte[] sec = BaseEncoding.base16().lowerCase().decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.sign(data, sec); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString, "" , "testSignNeg"); + } + + /** + * This tests private key tweak-add + */ + public static void testPrivKeyTweakAdd_1() throws AssertFailException { + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.privKeyTweakAdd( sec , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "A168571E189E6F9A7E2D657A4B53AE99B909F7E712D1C23CED28093CD57C88F3" , "testPrivKeyAdd_1"); + } + + /** + * This tests private key tweak-mul + */ + public static void testPrivKeyTweakMul_1() throws AssertFailException { + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.privKeyTweakMul( sec , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "97F8184235F101550F3C71C927507651BD3F1CDB4A5A33B8986ACF0DEE20FFFC" , "testPrivKeyMul_1"); + } + + /** + * This tests private key tweak-add uncompressed + */ + public static void testPrivKeyTweakAdd_2() throws AssertFailException { + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.pubKeyTweakAdd( pub , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "0411C6790F4B663CCE607BAAE08C43557EDC1A4D11D88DFCB3D841D0C6A941AF525A268E2A863C148555C48FB5FBA368E88718A46E205FABC3DBA2CCFFAB0796EF" , "testPrivKeyAdd_2"); + } + + /** + * This tests private key tweak-mul uncompressed + */ + public static void testPrivKeyTweakMul_2() throws AssertFailException { + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + byte[] data = BaseEncoding.base16().lowerCase().decode("3982F19BEF1615BCCFBB05E321C10E1D4CBA3DF0E841C2E41EEB6016347653C3".toLowerCase()); //sha256hash of "tweak" + + byte[] resultArr = NativeSecp256k1.pubKeyTweakMul( pub , data ); + String sigString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( sigString , "04E0FE6FE55EBCA626B98A807F6CAF654139E14E5E3698F01A9A658E21DC1D2791EC060D4F412A794D5370F672BC94B722640B5F76914151CFCA6E712CA48CC589" , "testPrivKeyMul_2"); + } + + /** + * This tests seed randomization + */ + public static void testRandomize() throws AssertFailException { + byte[] seed = BaseEncoding.base16().lowerCase().decode("A441B15FE9A3CF56661190A0B93B9DEC7D04127288CC87250967CF3B52894D11".toLowerCase()); //sha256hash of "random" + boolean result = NativeSecp256k1.randomize(seed); + assertEquals( result, true, "testRandomize"); + } + + public static void testCreateECDHSecret() throws AssertFailException{ + + byte[] sec = BaseEncoding.base16().lowerCase().decode("67E56582298859DDAE725F972992A07C6C4FB9F62A8FFF58CE3CA926A1063530".toLowerCase()); + byte[] pub = BaseEncoding.base16().lowerCase().decode("040A629506E1B65CD9D2E0BA9C75DF9C4FED0DB16DC9625ED14397F0AFC836FAE595DC53F8B0EFE61E703075BD9B143BAC75EC0E19F82A2208CAEB32BE53414C40".toLowerCase()); + + byte[] resultArr = NativeSecp256k1.createECDHSecret(sec, pub); + String ecdhString = javax.xml.bind.DatatypeConverter.printHexBinary(resultArr); + assertEquals( ecdhString, "2A2A67007A926E6594AF3EB564FC74005B37A9C8AEF2033C4552051B5C87F043" , "testCreateECDHSecret"); + } + + public static void main(String[] args) throws AssertFailException{ + + + System.out.println("\n libsecp256k1 enabled: " + Secp256k1Context.isEnabled() + "\n"); + + assertEquals( Secp256k1Context.isEnabled(), true, "isEnabled" ); + + //Test verify() success/fail + testVerifyPos(); + testVerifyNeg(); + + //Test secKeyVerify() success/fail + testSecKeyVerifyPos(); + testSecKeyVerifyNeg(); + + //Test computePubkey() success/fail + testPubKeyCreatePos(); + testPubKeyCreateNeg(); + + //Test sign() success/fail + testSignPos(); + testSignNeg(); + + //Test privKeyTweakAdd() 1 + testPrivKeyTweakAdd_1(); + + //Test privKeyTweakMul() 2 + testPrivKeyTweakMul_1(); + + //Test privKeyTweakAdd() 3 + testPrivKeyTweakAdd_2(); + + //Test privKeyTweakMul() 4 + testPrivKeyTweakMul_2(); + + //Test randomize() + testRandomize(); + + //Test ECDH + testCreateECDHSecret(); + + NativeSecp256k1.cleanup(); + + System.out.println(" All tests passed." ); + + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java new file mode 100644 index 00000000..04732ba0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/NativeSecp256k1Util.java @@ -0,0 +1,45 @@ +/* + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoin; + +public class NativeSecp256k1Util{ + + public static void assertEquals( int val, int val2, String message ) throws AssertFailException{ + if( val != val2 ) + throw new AssertFailException("FAIL: " + message); + } + + public static void assertEquals( boolean val, boolean val2, String message ) throws AssertFailException{ + if( val != val2 ) + throw new AssertFailException("FAIL: " + message); + else + System.out.println("PASS: " + message); + } + + public static void assertEquals( String val, String val2, String message ) throws AssertFailException{ + if( !val.equals(val2) ) + throw new AssertFailException("FAIL: " + message); + else + System.out.println("PASS: " + message); + } + + public static class AssertFailException extends Exception { + public AssertFailException(String message) { + super( message ); + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java new file mode 100644 index 00000000..216c986a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org/bitcoin/Secp256k1Context.java @@ -0,0 +1,51 @@ +/* + * Copyright 2014-2016 the libsecp256k1 contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.bitcoin; + +/** + * This class holds the context reference used in native methods + * to handle ECDSA operations. + */ +public class Secp256k1Context { + private static final boolean enabled; //true if the library is loaded + private static final long context; //ref to pointer to context obj + + static { //static initializer + boolean isEnabled = true; + long contextRef = -1; + try { + System.loadLibrary("secp256k1"); + contextRef = secp256k1_init_context(); + } catch (UnsatisfiedLinkError e) { + System.out.println("UnsatisfiedLinkError: " + e.toString()); + isEnabled = false; + } + enabled = isEnabled; + context = contextRef; + } + + public static boolean isEnabled() { + return enabled; + } + + public static long getContext() { + if(!enabled) return -1; //sanity check + return context; + } + + private static native long secp256k1_init_context(); +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c new file mode 100644 index 00000000..bcef7b32 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.c @@ -0,0 +1,377 @@ +#include +#include +#include +#include "org_bitcoin_NativeSecp256k1.h" +#include "include/secp256k1.h" +#include "include/secp256k1_ecdh.h" +#include "include/secp256k1_recovery.h" + + +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone + (JNIEnv* env, jclass classObject, jlong ctx_l) +{ + const secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + jlong ctx_clone_l = (uintptr_t) secp256k1_context_clone(ctx); + + (void)classObject;(void)env; + + return ctx_clone_l; + +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + const unsigned char* seed = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + (void)classObject; + + return secp256k1_context_randomize(ctx, seed); + +} + +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context + (JNIEnv* env, jclass classObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + secp256k1_context_destroy(ctx); + + (void)classObject;(void)env; +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint siglen, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* sigdata = { (unsigned char*) (data + 32) }; + const unsigned char* pubdata = { (unsigned char*) (data + siglen + 32) }; + + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pubkey; + + int ret = secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigdata, siglen); + + if( ret ) { + ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); + + if( ret ) { + ret = secp256k1_ecdsa_verify(ctx, &sig, data, &pubkey); + } + } + + (void)classObject; + + return ret; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* data = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + unsigned char* secKey = (unsigned char*) (data + 32); + + jobjectArray retArray; + jbyteArray sigArray, intsByteArray; + unsigned char intsarray[2]; + + secp256k1_ecdsa_signature sig[72]; + + int ret = secp256k1_ecdsa_sign(ctx, sig, data, secKey, NULL, NULL ); + + unsigned char outputSer[72]; + size_t outputLen = 72; + + if( ret ) { + int ret2 = secp256k1_ecdsa_signature_serialize_der(ctx,outputSer, &outputLen, sig ); (void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + sigArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, sigArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, sigArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + (void)classObject; + + return secp256k1_ec_seckey_verify(ctx, secKey); +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + const unsigned char* secKey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + + secp256k1_pubkey pubkey; + + jobjectArray retArray; + jbyteArray pubkeyArray, intsByteArray; + unsigned char intsarray[2]; + + int ret = secp256k1_ec_pubkey_create(ctx, &pubkey, secKey); + + unsigned char outputSer[65]; + size_t outputLen = 65; + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubkeyArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubkeyArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubkeyArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; + +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (privkey + 32); + + jobjectArray retArray; + jbyteArray privArray, intsByteArray; + unsigned char intsarray[2]; + + int privkeylen = 32; + + int ret = secp256k1_ec_privkey_tweak_add(ctx, privkey, tweak); + + intsarray[0] = privkeylen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + privArray = (*env)->NewByteArray(env, privkeylen); + (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); + (*env)->SetObjectArrayElement(env, retArray, 0, privArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* privkey = (unsigned char*) (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (privkey + 32); + + jobjectArray retArray; + jbyteArray privArray, intsByteArray; + unsigned char intsarray[2]; + + int privkeylen = 32; + + int ret = secp256k1_ec_privkey_tweak_mul(ctx, privkey, tweak); + + intsarray[0] = privkeylen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + privArray = (*env)->NewByteArray(env, privkeylen); + (*env)->SetByteArrayRegion(env, privArray, 0, privkeylen, (jbyte*)privkey); + (*env)->SetObjectArrayElement(env, retArray, 0, privArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; +/* secp256k1_pubkey* pubkey = (secp256k1_pubkey*) (*env)->GetDirectBufferAddress(env, byteBufferObject);*/ + unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (pkey + publen); + + jobjectArray retArray; + jbyteArray pubArray, intsByteArray; + unsigned char intsarray[2]; + unsigned char outputSer[65]; + size_t outputLen = 65; + + secp256k1_pubkey pubkey; + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); + + if( ret ) { + ret = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, tweak); + } + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + unsigned char* pkey = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* tweak = (unsigned char*) (pkey + publen); + + jobjectArray retArray; + jbyteArray pubArray, intsByteArray; + unsigned char intsarray[2]; + unsigned char outputSer[65]; + size_t outputLen = 65; + + secp256k1_pubkey pubkey; + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pkey, publen); + + if ( ret ) { + ret = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, tweak); + } + + if( ret ) { + int ret2 = secp256k1_ec_pubkey_serialize(ctx,outputSer, &outputLen, &pubkey,SECP256K1_EC_UNCOMPRESSED );(void)ret2; + } + + intsarray[0] = outputLen; + intsarray[1] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + pubArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, pubArray, 0, outputLen, (jbyte*)outputSer); + (*env)->SetObjectArrayElement(env, retArray, 0, pubArray); + + intsByteArray = (*env)->NewByteArray(env, 2); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 2, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} + +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1pubkey_1combine + (JNIEnv * env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint numkeys) +{ + (void)classObject;(void)env;(void)byteBufferObject;(void)ctx_l;(void)numkeys; + + return 0; +} + +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen) +{ + secp256k1_context *ctx = (secp256k1_context*)(uintptr_t)ctx_l; + const unsigned char* secdata = (*env)->GetDirectBufferAddress(env, byteBufferObject); + const unsigned char* pubdata = (const unsigned char*) (secdata + 32); + + jobjectArray retArray; + jbyteArray outArray, intsByteArray; + unsigned char intsarray[1]; + secp256k1_pubkey pubkey; + unsigned char nonce_res[32]; + size_t outputLen = 32; + + int ret = secp256k1_ec_pubkey_parse(ctx, &pubkey, pubdata, publen); + + if (ret) { + ret = secp256k1_ecdh( + ctx, + nonce_res, + &pubkey, + secdata + ); + } + + intsarray[0] = ret; + + retArray = (*env)->NewObjectArray(env, 2, + (*env)->FindClass(env, "[B"), + (*env)->NewByteArray(env, 1)); + + outArray = (*env)->NewByteArray(env, outputLen); + (*env)->SetByteArrayRegion(env, outArray, 0, 32, (jbyte*)nonce_res); + (*env)->SetObjectArrayElement(env, retArray, 0, outArray); + + intsByteArray = (*env)->NewByteArray(env, 1); + (*env)->SetByteArrayRegion(env, intsByteArray, 0, 1, (jbyte*)intsarray); + (*env)->SetObjectArrayElement(env, retArray, 1, intsByteArray); + + (void)classObject; + + return retArray; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h new file mode 100644 index 00000000..fe613c9e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_NativeSecp256k1.h @@ -0,0 +1,119 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#include "include/secp256k1.h" +/* Header for class org_bitcoin_NativeSecp256k1 */ + +#ifndef _Included_org_bitcoin_NativeSecp256k1 +#define _Included_org_bitcoin_NativeSecp256k1 +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ctx_clone + * Signature: (J)J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ctx_1clone + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_context_randomize + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1context_1randomize + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_privkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_privkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1privkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_pubkey_tweak_add + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1add + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_pubkey_tweak_mul + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1pubkey_1tweak_1mul + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_destroy_context + * Signature: (J)V + */ +SECP256K1_API void JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1destroy_1context + (JNIEnv *, jclass, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdsa_verify + * Signature: (Ljava/nio/ByteBuffer;JII)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1verify + (JNIEnv *, jclass, jobject, jlong, jint, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdsa_sign + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdsa_1sign + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_seckey_verify + * Signature: (Ljava/nio/ByteBuffer;J)I + */ +SECP256K1_API jint JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1seckey_1verify + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_pubkey_create + * Signature: (Ljava/nio/ByteBuffer;J)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1create + (JNIEnv *, jclass, jobject, jlong); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ec_pubkey_parse + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ec_1pubkey_1parse + (JNIEnv *, jclass, jobject, jlong, jint); + +/* + * Class: org_bitcoin_NativeSecp256k1 + * Method: secp256k1_ecdh + * Signature: (Ljava/nio/ByteBuffer;JI)[[B + */ +SECP256K1_API jobjectArray JNICALL Java_org_bitcoin_NativeSecp256k1_secp256k1_1ecdh + (JNIEnv* env, jclass classObject, jobject byteBufferObject, jlong ctx_l, jint publen); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c new file mode 100644 index 00000000..a52939e7 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.c @@ -0,0 +1,15 @@ +#include +#include +#include "org_bitcoin_Secp256k1Context.h" +#include "include/secp256k1.h" + +SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context + (JNIEnv* env, jclass classObject) +{ + secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + (void)classObject;(void)env; + + return (uintptr_t)ctx; +} + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h new file mode 100644 index 00000000..0d2bc84b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/java/org_bitcoin_Secp256k1Context.h @@ -0,0 +1,22 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +#include "include/secp256k1.h" +/* Header for class org_bitcoin_Secp256k1Context */ + +#ifndef _Included_org_bitcoin_Secp256k1Context +#define _Included_org_bitcoin_Secp256k1Context +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_bitcoin_Secp256k1Context + * Method: secp256k1_init_context + * Signature: ()J + */ +SECP256K1_API jlong JNICALL Java_org_bitcoin_Secp256k1Context_secp256k1_1init_1context + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include new file mode 100644 index 00000000..e3088b46 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/Makefile.am.include @@ -0,0 +1,8 @@ +include_HEADERS += include/secp256k1_ecdh.h +noinst_HEADERS += src/modules/ecdh/main_impl.h +noinst_HEADERS += src/modules/ecdh/tests_impl.h +if USE_BENCHMARK +noinst_PROGRAMS += bench_ecdh +bench_ecdh_SOURCES = src/bench_ecdh.c +bench_ecdh_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) +endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h new file mode 100644 index 00000000..9e30fb73 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/main_impl.h @@ -0,0 +1,54 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_MODULE_ECDH_MAIN_ +#define _SECP256K1_MODULE_ECDH_MAIN_ + +#include "include/secp256k1_ecdh.h" +#include "ecmult_const_impl.h" + +int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *result, const secp256k1_pubkey *point, const unsigned char *scalar) { + int ret = 0; + int overflow = 0; + secp256k1_gej res; + secp256k1_ge pt; + secp256k1_scalar s; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(result != NULL); + ARG_CHECK(point != NULL); + ARG_CHECK(scalar != NULL); + + secp256k1_pubkey_load(ctx, &pt, point); + secp256k1_scalar_set_b32(&s, scalar, &overflow); + if (overflow || secp256k1_scalar_is_zero(&s)) { + ret = 0; + } else { + unsigned char x[32]; + unsigned char y[1]; + secp256k1_sha256_t sha; + + secp256k1_ecmult_const(&res, &pt, &s); + secp256k1_ge_set_gej(&pt, &res); + /* Compute a hash of the point in compressed form + * Note we cannot use secp256k1_eckey_pubkey_serialize here since it does not + * expect its output to be secret and has a timing sidechannel. */ + secp256k1_fe_normalize(&pt.x); + secp256k1_fe_normalize(&pt.y); + secp256k1_fe_get_b32(x, &pt.x); + y[0] = 0x02 | secp256k1_fe_is_odd(&pt.y); + + secp256k1_sha256_initialize(&sha); + secp256k1_sha256_write(&sha, y, sizeof(y)); + secp256k1_sha256_write(&sha, x, sizeof(x)); + secp256k1_sha256_finalize(&sha, result); + ret = 1; + } + + secp256k1_scalar_clear(&s); + return ret; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h new file mode 100644 index 00000000..85a5d0a9 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/ecdh/tests_impl.h @@ -0,0 +1,105 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_MODULE_ECDH_TESTS_ +#define _SECP256K1_MODULE_ECDH_TESTS_ + +void test_ecdh_api(void) { + /* Setup context that just counts errors */ + secp256k1_context *tctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_pubkey point; + unsigned char res[32]; + unsigned char s_one[32] = { 0 }; + int32_t ecount = 0; + s_one[31] = 1; + + secp256k1_context_set_error_callback(tctx, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(tctx, counting_illegal_callback_fn, &ecount); + CHECK(secp256k1_ec_pubkey_create(tctx, &point, s_one) == 1); + + /* Check all NULLs are detected */ + CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); + CHECK(ecount == 0); + CHECK(secp256k1_ecdh(tctx, NULL, &point, s_one) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdh(tctx, res, NULL, s_one) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdh(tctx, res, &point, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdh(tctx, res, &point, s_one) == 1); + CHECK(ecount == 3); + + /* Cleanup */ + secp256k1_context_destroy(tctx); +} + +void test_ecdh_generator_basepoint(void) { + unsigned char s_one[32] = { 0 }; + secp256k1_pubkey point[2]; + int i; + + s_one[31] = 1; + /* Check against pubkey creation when the basepoint is the generator */ + for (i = 0; i < 100; ++i) { + secp256k1_sha256_t sha; + unsigned char s_b32[32]; + unsigned char output_ecdh[32]; + unsigned char output_ser[32]; + unsigned char point_ser[33]; + size_t point_ser_len = sizeof(point_ser); + secp256k1_scalar s; + + random_scalar_order(&s); + secp256k1_scalar_get_b32(s_b32, &s); + + /* compute using ECDH function */ + CHECK(secp256k1_ec_pubkey_create(ctx, &point[0], s_one) == 1); + CHECK(secp256k1_ecdh(ctx, output_ecdh, &point[0], s_b32) == 1); + /* compute "explicitly" */ + CHECK(secp256k1_ec_pubkey_create(ctx, &point[1], s_b32) == 1); + CHECK(secp256k1_ec_pubkey_serialize(ctx, point_ser, &point_ser_len, &point[1], SECP256K1_EC_COMPRESSED) == 1); + CHECK(point_ser_len == sizeof(point_ser)); + secp256k1_sha256_initialize(&sha); + secp256k1_sha256_write(&sha, point_ser, point_ser_len); + secp256k1_sha256_finalize(&sha, output_ser); + /* compare */ + CHECK(memcmp(output_ecdh, output_ser, sizeof(output_ser)) == 0); + } +} + +void test_bad_scalar(void) { + unsigned char s_zero[32] = { 0 }; + unsigned char s_overflow[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 + }; + unsigned char s_rand[32] = { 0 }; + unsigned char output[32]; + secp256k1_scalar rand; + secp256k1_pubkey point; + + /* Create random point */ + random_scalar_order(&rand); + secp256k1_scalar_get_b32(s_rand, &rand); + CHECK(secp256k1_ec_pubkey_create(ctx, &point, s_rand) == 1); + + /* Try to multiply it by bad values */ + CHECK(secp256k1_ecdh(ctx, output, &point, s_zero) == 0); + CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 0); + /* ...and a good one */ + s_overflow[31] -= 1; + CHECK(secp256k1_ecdh(ctx, output, &point, s_overflow) == 1); +} + +void run_ecdh_tests(void) { + test_ecdh_api(); + test_ecdh_generator_basepoint(); + test_bad_scalar(); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include new file mode 100644 index 00000000..bf23c26e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/Makefile.am.include @@ -0,0 +1,8 @@ +include_HEADERS += include/secp256k1_recovery.h +noinst_HEADERS += src/modules/recovery/main_impl.h +noinst_HEADERS += src/modules/recovery/tests_impl.h +if USE_BENCHMARK +noinst_PROGRAMS += bench_recover +bench_recover_SOURCES = src/bench_recover.c +bench_recover_LDADD = libsecp256k1.la $(SECP_LIBS) $(COMMON_LIB) +endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h new file mode 100755 index 00000000..c6fbe239 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/main_impl.h @@ -0,0 +1,193 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_MODULE_RECOVERY_MAIN_ +#define _SECP256K1_MODULE_RECOVERY_MAIN_ + +#include "include/secp256k1_recovery.h" + +static void secp256k1_ecdsa_recoverable_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, int* recid, const secp256k1_ecdsa_recoverable_signature* sig) { + (void)ctx; + if (sizeof(secp256k1_scalar) == 32) { + /* When the secp256k1_scalar type is exactly 32 byte, use its + * representation inside secp256k1_ecdsa_signature, as conversion is very fast. + * Note that secp256k1_ecdsa_signature_save must use the same representation. */ + memcpy(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); + } else { + secp256k1_scalar_set_b32(r, &sig->data[0], NULL); + secp256k1_scalar_set_b32(s, &sig->data[32], NULL); + } + *recid = sig->data[64]; +} + +static void secp256k1_ecdsa_recoverable_signature_save(secp256k1_ecdsa_recoverable_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s, int recid) { + if (sizeof(secp256k1_scalar) == 32) { + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); + } else { + secp256k1_scalar_get_b32(&sig->data[0], r); + secp256k1_scalar_get_b32(&sig->data[32], s); + } + sig->data[64] = recid; +} + +int secp256k1_ecdsa_recoverable_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature* sig, const unsigned char *input64, int recid) { + secp256k1_scalar r, s; + int ret = 1; + int overflow = 0; + + (void)ctx; + ARG_CHECK(sig != NULL); + ARG_CHECK(input64 != NULL); + ARG_CHECK(recid >= 0 && recid <= 3); + + secp256k1_scalar_set_b32(&r, &input64[0], &overflow); + ret &= !overflow; + secp256k1_scalar_set_b32(&s, &input64[32], &overflow); + ret &= !overflow; + if (ret) { + secp256k1_ecdsa_recoverable_signature_save(sig, &r, &s, recid); + } else { + memset(sig, 0, sizeof(*sig)); + } + return ret; +} + +int secp256k1_ecdsa_recoverable_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, int *recid, const secp256k1_ecdsa_recoverable_signature* sig) { + secp256k1_scalar r, s; + + (void)ctx; + ARG_CHECK(output64 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(recid != NULL); + + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, recid, sig); + secp256k1_scalar_get_b32(&output64[0], &r); + secp256k1_scalar_get_b32(&output64[32], &s); + return 1; +} + +int secp256k1_ecdsa_recoverable_signature_convert(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const secp256k1_ecdsa_recoverable_signature* sigin) { + secp256k1_scalar r, s; + int recid; + + (void)ctx; + ARG_CHECK(sig != NULL); + ARG_CHECK(sigin != NULL); + + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, sigin); + secp256k1_ecdsa_signature_save(sig, &r, &s); + return 1; +} + +static int secp256k1_ecdsa_sig_recover(const secp256k1_ecmult_context *ctx, const secp256k1_scalar *sigr, const secp256k1_scalar* sigs, secp256k1_ge *pubkey, const secp256k1_scalar *message, int recid) { + unsigned char brx[32]; + secp256k1_fe fx; + secp256k1_ge x; + secp256k1_gej xj; + secp256k1_scalar rn, u1, u2; + secp256k1_gej qj; + int r; + + if (secp256k1_scalar_is_zero(sigr) || secp256k1_scalar_is_zero(sigs)) { + return 0; + } + + secp256k1_scalar_get_b32(brx, sigr); + r = secp256k1_fe_set_b32(&fx, brx); + (void)r; + VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */ + if (recid & 2) { + if (secp256k1_fe_cmp_var(&fx, &secp256k1_ecdsa_const_p_minus_order) >= 0) { + return 0; + } + secp256k1_fe_add(&fx, &secp256k1_ecdsa_const_order_as_fe); + } + if (!secp256k1_ge_set_xo_var(&x, &fx, recid & 1)) { + return 0; + } + secp256k1_gej_set_ge(&xj, &x); + secp256k1_scalar_inverse_var(&rn, sigr); + secp256k1_scalar_mul(&u1, &rn, message); + secp256k1_scalar_negate(&u1, &u1); + secp256k1_scalar_mul(&u2, &rn, sigs); + secp256k1_ecmult(ctx, &qj, &xj, &u2, &u1); + secp256k1_ge_set_gej_var(pubkey, &qj); + return !secp256k1_gej_is_infinity(&qj); +} + +int secp256k1_ecdsa_sign_recoverable(const secp256k1_context* ctx, secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { + secp256k1_scalar r, s; + secp256k1_scalar sec, non, msg; + int recid; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(seckey != NULL); + if (noncefp == NULL) { + noncefp = secp256k1_nonce_function_default; + } + + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + /* Fail if the secret key is invalid. */ + if (!overflow && !secp256k1_scalar_is_zero(&sec)) { + unsigned char nonce32[32]; + unsigned int count = 0; + secp256k1_scalar_set_b32(&msg, msg32, NULL); + while (1) { + ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + if (!ret) { + break; + } + secp256k1_scalar_set_b32(&non, nonce32, &overflow); + if (!secp256k1_scalar_is_zero(&non) && !overflow) { + if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, &recid)) { + break; + } + } + count++; + } + memset(nonce32, 0, 32); + secp256k1_scalar_clear(&msg); + secp256k1_scalar_clear(&non); + secp256k1_scalar_clear(&sec); + } + if (ret) { + secp256k1_ecdsa_recoverable_signature_save(signature, &r, &s, recid); + } else { + memset(signature, 0, sizeof(*signature)); + } + return ret; +} + +int secp256k1_ecdsa_recover(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const secp256k1_ecdsa_recoverable_signature *signature, const unsigned char *msg32) { + secp256k1_ge q; + secp256k1_scalar r, s; + secp256k1_scalar m; + int recid; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(pubkey != NULL); + + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, signature); + VERIFY_CHECK(recid >= 0 && recid < 4); /* should have been caught in parse_compact */ + secp256k1_scalar_set_b32(&m, msg32, NULL); + if (secp256k1_ecdsa_sig_recover(&ctx->ecmult_ctx, &r, &s, &q, &m, recid)) { + secp256k1_pubkey_save(pubkey, &q); + return 1; + } else { + memset(pubkey, 0, sizeof(*pubkey)); + return 0; + } +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h new file mode 100644 index 00000000..765c7dd8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery/tests_impl.h @@ -0,0 +1,393 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_MODULE_RECOVERY_TESTS_ +#define _SECP256K1_MODULE_RECOVERY_TESTS_ + +static int recovery_test_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + (void) msg32; + (void) key32; + (void) algo16; + (void) data; + + /* On the first run, return 0 to force a second run */ + if (counter == 0) { + memset(nonce32, 0, 32); + return 1; + } + /* On the second run, return an overflow to force a third run */ + if (counter == 1) { + memset(nonce32, 0xff, 32); + return 1; + } + /* On the next run, return a valid nonce, but flip a coin as to whether or not to fail signing. */ + memset(nonce32, 1, 32); + return secp256k1_rand_bits(1); +} + +void test_ecdsa_recovery_api(void) { + /* Setup contexts that just count errors */ + secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + secp256k1_pubkey pubkey; + secp256k1_pubkey recpubkey; + secp256k1_ecdsa_signature normal_sig; + secp256k1_ecdsa_recoverable_signature recsig; + unsigned char privkey[32] = { 1 }; + unsigned char message[32] = { 2 }; + int32_t ecount = 0; + int recid = 0; + unsigned char sig[74]; + unsigned char zero_privkey[32] = { 0 }; + unsigned char over_privkey[32] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + secp256k1_context_set_error_callback(none, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_error_callback(both, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(none, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(both, counting_illegal_callback_fn, &ecount); + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Check bad contexts and NULLs for signing */ + ecount = 0; + CHECK(secp256k1_ecdsa_sign_recoverable(none, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(sign, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(vrfy, &recsig, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign_recoverable(both, NULL, message, privkey, NULL, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, NULL, privkey, NULL, NULL) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, NULL, NULL, NULL) == 0); + CHECK(ecount == 5); + /* This will fail or succeed randomly, and in either case will not ARG_CHECK failure */ + secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, recovery_test_nonce_function, NULL); + CHECK(ecount == 5); + /* These will all fail, but not in ARG_CHECK way */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, zero_privkey, NULL, NULL) == 0); + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, over_privkey, NULL, NULL) == 0); + /* This one will succeed. */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + CHECK(ecount == 5); + + /* Check signing with a goofy nonce function */ + + /* Check bad contexts and NULLs for recovery */ + ecount = 0; + CHECK(secp256k1_ecdsa_recover(none, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recover(sign, &recpubkey, &recsig, message) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(vrfy, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, message) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recover(both, NULL, &recsig, message) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, NULL, message) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_recover(both, &recpubkey, &recsig, NULL) == 0); + CHECK(ecount == 5); + + /* Check NULLs for conversion */ + CHECK(secp256k1_ecdsa_sign(both, &normal_sig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, NULL, &recsig) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, NULL) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(both, &normal_sig, &recsig) == 1); + + /* Check NULLs for de/serialization */ + CHECK(secp256k1_ecdsa_sign_recoverable(both, &recsig, message, privkey, NULL, NULL) == 1); + ecount = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, NULL, &recid, &recsig) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, NULL, &recsig) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(both, sig, &recid, &recsig) == 1); + + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, NULL, sig, recid) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, NULL, recid) == 0); + CHECK(ecount == 5); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, -1) == 0); + CHECK(ecount == 6); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, 5) == 0); + CHECK(ecount == 7); + /* overflow in signature will fail but not affect ecount */ + memcpy(sig, over_privkey, 32); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(both, &recsig, sig, recid) == 0); + CHECK(ecount == 7); + + /* cleanup */ + secp256k1_context_destroy(none); + secp256k1_context_destroy(sign); + secp256k1_context_destroy(vrfy); + secp256k1_context_destroy(both); +} + +void test_ecdsa_recovery_end_to_end(void) { + unsigned char extra[32] = {0x00}; + unsigned char privkey[32]; + unsigned char message[32]; + secp256k1_ecdsa_signature signature[5]; + secp256k1_ecdsa_recoverable_signature rsignature[5]; + unsigned char sig[74]; + secp256k1_pubkey pubkey; + secp256k1_pubkey recpubkey; + int recid = 0; + + /* Generate a random key and message. */ + { + secp256k1_scalar msg, key; + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_scalar_get_b32(privkey, &key); + secp256k1_scalar_get_b32(message, &msg); + } + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Serialize/parse compact and verify/recover. */ + extra[0] = 0; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[0], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[4], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[1], message, privkey, NULL, extra) == 1); + extra[31] = 1; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[2], message, privkey, NULL, extra) == 1); + extra[31] = 0; + extra[0] = 1; + CHECK(secp256k1_ecdsa_sign_recoverable(ctx, &rsignature[3], message, privkey, NULL, extra) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(memcmp(&signature[4], &signature[0], 64) == 0); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); + memset(&rsignature[4], 0, sizeof(rsignature[4])); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 1); + /* Parse compact (with recovery id) and recover. */ + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 1); + CHECK(memcmp(&pubkey, &recpubkey, sizeof(pubkey)) == 0); + /* Serialize/destroy/parse signature and verify again. */ + CHECK(secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx, sig, &recid, &rsignature[4]) == 1); + sig[secp256k1_rand_bits(6)] += 1 + secp256k1_rand_int(255); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsignature[4], sig, recid) == 1); + CHECK(secp256k1_ecdsa_recoverable_signature_convert(ctx, &signature[4], &rsignature[4]) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[4], message, &pubkey) == 0); + /* Recover again */ + CHECK(secp256k1_ecdsa_recover(ctx, &recpubkey, &rsignature[4], message) == 0 || + memcmp(&pubkey, &recpubkey, sizeof(pubkey)) != 0); +} + +/* Tests several edge cases. */ +void test_ecdsa_recovery_edge_cases(void) { + const unsigned char msg32[32] = { + 'T', 'h', 'i', 's', ' ', 'i', 's', ' ', + 'a', ' ', 'v', 'e', 'r', 'y', ' ', 's', + 'e', 'c', 'r', 'e', 't', ' ', 'm', 'e', + 's', 's', 'a', 'g', 'e', '.', '.', '.' + }; + const unsigned char sig64[64] = { + /* Generated by signing the above message with nonce 'This is the nonce we will use...' + * and secret key 0 (which is not valid), resulting in recid 0. */ + 0x67, 0xCB, 0x28, 0x5F, 0x9C, 0xD1, 0x94, 0xE8, + 0x40, 0xD6, 0x29, 0x39, 0x7A, 0xF5, 0x56, 0x96, + 0x62, 0xFD, 0xE4, 0x46, 0x49, 0x99, 0x59, 0x63, + 0x17, 0x9A, 0x7D, 0xD1, 0x7B, 0xD2, 0x35, 0x32, + 0x4B, 0x1B, 0x7D, 0xF3, 0x4C, 0xE1, 0xF6, 0x8E, + 0x69, 0x4F, 0xF6, 0xF1, 0x1A, 0xC7, 0x51, 0xDD, + 0x7D, 0xD7, 0x3E, 0x38, 0x7E, 0xE4, 0xFC, 0x86, + 0x6E, 0x1B, 0xE8, 0xEC, 0xC7, 0xDD, 0x95, 0x57 + }; + secp256k1_pubkey pubkey; + /* signature (r,s) = (4,4), which can be recovered with all 4 recids. */ + const unsigned char sigb64[64] = { + 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, 0x04, + 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, 0x04, + }; + secp256k1_pubkey pubkeyb; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + int recid; + + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 0)); + CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 1)); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 2)); + CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sig64, 3)); + CHECK(!secp256k1_ecdsa_recover(ctx, &pubkey, &rsig, msg32)); + + for (recid = 0; recid < 4; recid++) { + int i; + int recid2; + /* (4,4) encoded in DER. */ + unsigned char sigbder[8] = {0x30, 0x06, 0x02, 0x01, 0x04, 0x02, 0x01, 0x04}; + unsigned char sigcder_zr[7] = {0x30, 0x05, 0x02, 0x00, 0x02, 0x01, 0x01}; + unsigned char sigcder_zs[7] = {0x30, 0x05, 0x02, 0x01, 0x01, 0x02, 0x00}; + unsigned char sigbderalt1[39] = { + 0x30, 0x25, 0x02, 0x20, 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, 0x04, 0x02, 0x01, 0x04, + }; + unsigned char sigbderalt2[39] = { + 0x30, 0x25, 0x02, 0x01, 0x04, 0x02, 0x20, 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, 0x04, + }; + unsigned char sigbderalt3[40] = { + 0x30, 0x26, 0x02, 0x21, 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, 0x04, 0x02, 0x01, 0x04, + }; + unsigned char sigbderalt4[40] = { + 0x30, 0x26, 0x02, 0x01, 0x04, 0x02, 0x21, 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, 0x04, + }; + /* (order + r,4) encoded in DER. */ + unsigned char sigbderlong[40] = { + 0x30, 0x26, 0x02, 0x21, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xBA, 0xAE, 0xDC, + 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, + 0x8C, 0xD0, 0x36, 0x41, 0x45, 0x02, 0x01, 0x04 + }; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 1); + for (recid2 = 0; recid2 < 4; recid2++) { + secp256k1_pubkey pubkey2b; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigb64, recid2) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkey2b, &rsig, msg32) == 1); + /* Verifying with (order + r,4) should always fail. */ + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderlong, sizeof(sigbderlong)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + } + /* DER parsing tests. */ + /* Zero length r/s. */ + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zr, sizeof(sigcder_zr)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder_zs, sizeof(sigcder_zs)) == 0); + /* Leading zeros. */ + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt1, sizeof(sigbderalt1)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt2, sizeof(sigbderalt2)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 0); + sigbderalt3[4] = 1; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt3, sizeof(sigbderalt3)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + sigbderalt4[7] = 1; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbderalt4, sizeof(sigbderalt4)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + /* Damage signature. */ + sigbder[7]++; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + sigbder[7]--; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, 6) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder) - 1) == 0); + for(i = 0; i < 8; i++) { + int c; + unsigned char orig = sigbder[i]; + /*Try every single-byte change.*/ + for (c = 0; c < 256; c++) { + if (c == orig ) { + continue; + } + sigbder[i] = c; + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigbder, sizeof(sigbder)) == 0 || secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyb) == 0); + } + sigbder[i] = orig; + } + } + + /* Test r/s equal to zero */ + { + /* (1,1) encoded in DER. */ + unsigned char sigcder[8] = {0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01}; + unsigned char sigc64[64] = { + 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, 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, 0x01, + }; + secp256k1_pubkey pubkeyc; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyc, &rsig, msg32) == 1); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 1); + sigcder[4] = 0; + sigc64[31] = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); + sigcder[4] = 1; + sigcder[7] = 0; + sigc64[31] = 1; + sigc64[63] = 0; + CHECK(secp256k1_ecdsa_recoverable_signature_parse_compact(ctx, &rsig, sigc64, 0) == 1); + CHECK(secp256k1_ecdsa_recover(ctx, &pubkeyb, &rsig, msg32) == 0); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, sigcder, sizeof(sigcder)) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg32, &pubkeyc) == 0); + } +} + +void run_recovery_tests(void) { + int i; + for (i = 0; i < count; i++) { + test_ecdsa_recovery_api(); + } + for (i = 0; i < 64*count; i++) { + test_ecdsa_recovery_end_to_end(); + } + test_ecdsa_recovery_edge_cases(); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h new file mode 100644 index 00000000..7bb9c5be --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num.h @@ -0,0 +1,74 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_ +#define _SECP256K1_NUM_ + +#ifndef USE_NUM_NONE + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(USE_NUM_GMP) +#include "num_gmp.h" +#else +#error "Please select num implementation" +#endif + +/** Copy a number. */ +static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a); + +/** Convert a number's absolute value to a binary big-endian string. + * There must be enough place. */ +static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a); + +/** Set a number to the value of a binary big-endian string. */ +static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen); + +/** Compute a modular inverse. The input must be less than the modulus. */ +static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m); + +/** Compute the jacobi symbol (a|b). b must be positive and odd. */ +static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b); + +/** Compare the absolute value of two numbers. */ +static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b); + +/** Test whether two number are equal (including sign). */ +static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b); + +/** Add two (signed) numbers. */ +static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); + +/** Subtract two (signed) numbers. */ +static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); + +/** Multiply two (signed) numbers. */ +static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b); + +/** Replace a number by its remainder modulo m. M's sign is ignored. The result is a number between 0 and m-1, + even if r was negative. */ +static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m); + +/** Right-shift the passed number by bits bits. */ +static void secp256k1_num_shift(secp256k1_num *r, int bits); + +/** Check whether a number is zero. */ +static int secp256k1_num_is_zero(const secp256k1_num *a); + +/** Check whether a number is one. */ +static int secp256k1_num_is_one(const secp256k1_num *a); + +/** Check whether a number is strictly negative. */ +static int secp256k1_num_is_neg(const secp256k1_num *a); + +/** Change a number's sign. */ +static void secp256k1_num_negate(secp256k1_num *r); + +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h new file mode 100644 index 00000000..7dd81308 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp.h @@ -0,0 +1,20 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_REPR_ +#define _SECP256K1_NUM_REPR_ + +#include + +#define NUM_LIMBS ((256+GMP_NUMB_BITS-1)/GMP_NUMB_BITS) + +typedef struct { + mp_limb_t data[2*NUM_LIMBS]; + int neg; + int limbs; +} secp256k1_num; + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h new file mode 100644 index 00000000..3a46495e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h @@ -0,0 +1,288 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_REPR_IMPL_H_ +#define _SECP256K1_NUM_REPR_IMPL_H_ + +#include +#include +#include + +#include "util.h" +#include "num.h" + +#ifdef VERIFY +static void secp256k1_num_sanity(const secp256k1_num *a) { + VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0)); +} +#else +#define secp256k1_num_sanity(a) do { } while(0) +#endif + +static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a) { + *r = *a; +} + +static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a) { + unsigned char tmp[65]; + int len = 0; + int shift = 0; + if (a->limbs>1 || a->data[0] != 0) { + len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs); + } + while (shift < len && tmp[shift] == 0) shift++; + VERIFY_CHECK(len-shift <= (int)rlen); + memset(r, 0, rlen - len + shift); + if (len > shift) { + memcpy(r + rlen - len + shift, tmp + shift, len - shift); + } + memset(tmp, 0, sizeof(tmp)); +} + +static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) { + int len; + VERIFY_CHECK(alen > 0); + VERIFY_CHECK(alen <= 64); + len = mpn_set_str(r->data, a, alen, 256); + if (len == 0) { + r->data[0] = 0; + len = 1; + } + VERIFY_CHECK(len <= NUM_LIMBS*2); + r->limbs = len; + r->neg = 0; + while (r->limbs > 1 && r->data[r->limbs-1]==0) { + r->limbs--; + } +} + +static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs); + r->limbs = a->limbs; + if (c != 0) { + VERIFY_CHECK(r->limbs < 2*NUM_LIMBS); + r->data[r->limbs++] = c; + } +} + +static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs); + (void)c; + VERIFY_CHECK(c == 0); + r->limbs = a->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) { + r->limbs--; + } +} + +static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) { + secp256k1_num_sanity(r); + secp256k1_num_sanity(m); + + if (r->limbs >= m->limbs) { + mp_limb_t t[2*NUM_LIMBS]; + mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs); + memset(t, 0, sizeof(t)); + r->limbs = m->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) { + r->limbs--; + } + } + + if (r->neg && (r->limbs > 1 || r->data[0] != 0)) { + secp256k1_num_sub_abs(r, m, r); + r->neg = 0; + } +} + +static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m) { + int i; + mp_limb_t g[NUM_LIMBS+1]; + mp_limb_t u[NUM_LIMBS+1]; + mp_limb_t v[NUM_LIMBS+1]; + mp_size_t sn; + mp_size_t gn; + secp256k1_num_sanity(a); + secp256k1_num_sanity(m); + + /** mpn_gcdext computes: (G,S) = gcdext(U,V), where + * * G = gcd(U,V) + * * G = U*S + V*T + * * U has equal or more limbs than V, and V has no padding + * If we set U to be (a padded version of) a, and V = m: + * G = a*S + m*T + * G = a*S mod m + * Assuming G=1: + * S = 1/a mod m + */ + VERIFY_CHECK(m->limbs <= NUM_LIMBS); + VERIFY_CHECK(m->data[m->limbs-1] != 0); + for (i = 0; i < m->limbs; i++) { + u[i] = (i < a->limbs) ? a->data[i] : 0; + v[i] = m->data[i]; + } + sn = NUM_LIMBS+1; + gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs); + (void)gn; + VERIFY_CHECK(gn == 1); + VERIFY_CHECK(g[0] == 1); + r->neg = a->neg ^ m->neg; + if (sn < 0) { + mpn_sub(r->data, m->data, m->limbs, r->data, -sn); + r->limbs = m->limbs; + while (r->limbs > 1 && r->data[r->limbs-1]==0) { + r->limbs--; + } + } else { + r->limbs = sn; + } + memset(g, 0, sizeof(g)); + memset(u, 0, sizeof(u)); + memset(v, 0, sizeof(v)); +} + +static int secp256k1_num_jacobi(const secp256k1_num *a, const secp256k1_num *b) { + int ret; + mpz_t ga, gb; + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + VERIFY_CHECK(!b->neg && (b->limbs > 0) && (b->data[0] & 1)); + + mpz_inits(ga, gb, NULL); + + mpz_import(gb, b->limbs, -1, sizeof(mp_limb_t), 0, 0, b->data); + mpz_import(ga, a->limbs, -1, sizeof(mp_limb_t), 0, 0, a->data); + if (a->neg) { + mpz_neg(ga, ga); + } + + ret = mpz_jacobi(ga, gb); + + mpz_clears(ga, gb, NULL); + + return ret; +} + +static int secp256k1_num_is_one(const secp256k1_num *a) { + return (a->limbs == 1 && a->data[0] == 1); +} + +static int secp256k1_num_is_zero(const secp256k1_num *a) { + return (a->limbs == 1 && a->data[0] == 0); +} + +static int secp256k1_num_is_neg(const secp256k1_num *a) { + return (a->limbs > 1 || a->data[0] != 0) && a->neg; +} + +static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b) { + if (a->limbs > b->limbs) { + return 1; + } + if (a->limbs < b->limbs) { + return -1; + } + return mpn_cmp(a->data, b->data, a->limbs); +} + +static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b) { + if (a->limbs > b->limbs) { + return 0; + } + if (a->limbs < b->limbs) { + return 0; + } + if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) { + return 0; + } + return mpn_cmp(a->data, b->data, a->limbs) == 0; +} + +static void secp256k1_num_subadd(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b, int bneg) { + if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */ + r->neg = a->neg; + if (a->limbs >= b->limbs) { + secp256k1_num_add_abs(r, a, b); + } else { + secp256k1_num_add_abs(r, b, a); + } + } else { + if (secp256k1_num_cmp(a, b) > 0) { + r->neg = a->neg; + secp256k1_num_sub_abs(r, a, b); + } else { + r->neg = b->neg ^ bneg; + secp256k1_num_sub_abs(r, b, a); + } + } +} + +static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + secp256k1_num_subadd(r, a, b, 0); +} + +static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + secp256k1_num_subadd(r, a, b, 1); +} + +static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) { + mp_limb_t tmp[2*NUM_LIMBS+1]; + secp256k1_num_sanity(a); + secp256k1_num_sanity(b); + + VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1); + if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) { + r->limbs = 1; + r->neg = 0; + r->data[0] = 0; + return; + } + if (a->limbs >= b->limbs) { + mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs); + } else { + mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs); + } + r->limbs = a->limbs + b->limbs; + if (r->limbs > 1 && tmp[r->limbs - 1]==0) { + r->limbs--; + } + VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS); + mpn_copyi(r->data, tmp, r->limbs); + r->neg = a->neg ^ b->neg; + memset(tmp, 0, sizeof(tmp)); +} + +static void secp256k1_num_shift(secp256k1_num *r, int bits) { + if (bits % GMP_NUMB_BITS) { + /* Shift within limbs. */ + mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS); + } + if (bits >= GMP_NUMB_BITS) { + int i; + /* Shift full limbs. */ + for (i = 0; i < r->limbs; i++) { + int index = i + (bits / GMP_NUMB_BITS); + if (index < r->limbs && index < 2*NUM_LIMBS) { + r->data[i] = r->data[index]; + } else { + r->data[i] = 0; + } + } + } + while (r->limbs>1 && r->data[r->limbs-1]==0) { + r->limbs--; + } +} + +static void secp256k1_num_negate(secp256k1_num *r) { + r->neg ^= 1; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h new file mode 100644 index 00000000..0b0e3a07 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/num_impl.h @@ -0,0 +1,24 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_NUM_IMPL_H_ +#define _SECP256K1_NUM_IMPL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include "num.h" + +#if defined(USE_NUM_GMP) +#include "num_gmp_impl.h" +#elif defined(USE_NUM_NONE) +/* Nothing. */ +#else +#error "Please select num implementation" +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h new file mode 100644 index 00000000..27e9d837 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar.h @@ -0,0 +1,106 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_ +#define _SECP256K1_SCALAR_ + +#include "num.h" + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(EXHAUSTIVE_TEST_ORDER) +#include "scalar_low.h" +#elif defined(USE_SCALAR_4X64) +#include "scalar_4x64.h" +#elif defined(USE_SCALAR_8X32) +#include "scalar_8x32.h" +#else +#error "Please select scalar implementation" +#endif + +/** Clear a scalar to prevent the leak of sensitive data. */ +static void secp256k1_scalar_clear(secp256k1_scalar *r); + +/** Access bits from a scalar. All requested bits must belong to the same 32-bit limb. */ +static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count); + +/** Access bits from a scalar. Not constant time. */ +static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count); + +/** Set a scalar from a big endian byte array. */ +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *bin, int *overflow); + +/** Set a scalar to an unsigned integer. */ +static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v); + +/** Convert a scalar to a byte array. */ +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a); + +/** Add two scalars together (modulo the group order). Returns whether it overflowed. */ +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); + +/** Conditionally add a power of two to a scalar. The result is not allowed to overflow. */ +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag); + +/** Multiply two scalars (modulo the group order). */ +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b); + +/** Shift a scalar right by some amount strictly between 0 and 16, returning + * the low bits that were shifted off */ +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n); + +/** Compute the square of a scalar (modulo the group order). */ +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a); + +/** Compute the inverse of a scalar (modulo the group order). */ +static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *a); + +/** Compute the inverse of a scalar (modulo the group order), without constant-time guarantee. */ +static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *a); + +/** Compute the complement of a scalar (modulo the group order). */ +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a); + +/** Check whether a scalar equals zero. */ +static int secp256k1_scalar_is_zero(const secp256k1_scalar *a); + +/** Check whether a scalar equals one. */ +static int secp256k1_scalar_is_one(const secp256k1_scalar *a); + +/** Check whether a scalar, considered as an nonnegative integer, is even. */ +static int secp256k1_scalar_is_even(const secp256k1_scalar *a); + +/** Check whether a scalar is higher than the group order divided by 2. */ +static int secp256k1_scalar_is_high(const secp256k1_scalar *a); + +/** Conditionally negate a number, in constant time. + * Returns -1 if the number was negated, 1 otherwise */ +static int secp256k1_scalar_cond_negate(secp256k1_scalar *a, int flag); + +#ifndef USE_NUM_NONE +/** Convert a scalar to a number. */ +static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a); + +/** Get the order of the group as a number. */ +static void secp256k1_scalar_order_get_num(secp256k1_num *r); +#endif + +/** Compare two scalars. */ +static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b); + +#ifdef USE_ENDOMORPHISM +/** Find r1 and r2 such that r1+r2*2^128 = a. */ +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); +/** Find r1 and r2 such that r1+r2*lambda = a, and r1 and r2 are maximum 128 bits long (see secp256k1_gej_mul_lambda). */ +static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a); +#endif + +/** Multiply a and b (without taking the modulus!), divide by 2**shift, and round to the nearest integer. Shift must be at least 256. */ +static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h new file mode 100644 index 00000000..cff40603 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64.h @@ -0,0 +1,19 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ + +#include + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef struct { + uint64_t d[4]; +} secp256k1_scalar; + +#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{((uint64_t)(d1)) << 32 | (d0), ((uint64_t)(d3)) << 32 | (d2), ((uint64_t)(d5)) << 32 | (d4), ((uint64_t)(d7)) << 32 | (d6)}} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h new file mode 100644 index 00000000..56e7bd82 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_4x64_impl.h @@ -0,0 +1,949 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ + +/* Limbs of the secp256k1 order. */ +#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL) +#define SECP256K1_N_1 ((uint64_t)0xBAAEDCE6AF48A03BULL) +#define SECP256K1_N_2 ((uint64_t)0xFFFFFFFFFFFFFFFEULL) +#define SECP256K1_N_3 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) + +/* Limbs of 2^256 minus the secp256k1 order. */ +#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) +#define SECP256K1_N_C_1 (~SECP256K1_N_1) +#define SECP256K1_N_C_2 (1) + +/* Limbs of half the secp256k1 order. */ +#define SECP256K1_N_H_0 ((uint64_t)0xDFE92F46681B20A0ULL) +#define SECP256K1_N_H_1 ((uint64_t)0x5D576E7357A4501DULL) +#define SECP256K1_N_H_2 ((uint64_t)0xFFFFFFFFFFFFFFFFULL) +#define SECP256K1_N_H_3 ((uint64_t)0x7FFFFFFFFFFFFFFFULL) + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { + r->d[0] = 0; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; +} + +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { + r->d[0] = v; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK((offset + count - 1) >> 6 == offset >> 6); + return (a->d[offset >> 6] >> (offset & 0x3F)) & ((((uint64_t)1) << count) - 1); +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK(count < 32); + VERIFY_CHECK(offset + count <= 256); + if ((offset + count - 1) >> 6 == offset >> 6) { + return secp256k1_scalar_get_bits(a, offset, count); + } else { + VERIFY_CHECK((offset >> 6) + 1 < 4); + return ((a->d[offset >> 6] >> (offset & 0x3F)) | (a->d[(offset >> 6) + 1] << (64 - (offset & 0x3F)))) & ((((uint64_t)1) << count) - 1); + } +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { + int yes = 0; + int no = 0; + no |= (a->d[3] < SECP256K1_N_3); /* No need for a > check. */ + no |= (a->d[2] < SECP256K1_N_2); + yes |= (a->d[2] > SECP256K1_N_2) & ~no; + no |= (a->d[1] < SECP256K1_N_1); + yes |= (a->d[1] > SECP256K1_N_1) & ~no; + yes |= (a->d[0] >= SECP256K1_N_0) & ~no; + return yes; +} + +SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, unsigned int overflow) { + uint128_t t; + VERIFY_CHECK(overflow <= 1); + t = (uint128_t)r->d[0] + overflow * SECP256K1_N_C_0; + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[1] + overflow * SECP256K1_N_C_1; + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[2] + overflow * SECP256K1_N_C_2; + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint64_t)r->d[3]; + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; + return overflow; +} + +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + int overflow; + uint128_t t = (uint128_t)a->d[0] + b->d[0]; + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[1] + b->d[1]; + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[2] + b->d[2]; + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)a->d[3] + b->d[3]; + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + overflow = t + secp256k1_scalar_check_overflow(r); + VERIFY_CHECK(overflow == 0 || overflow == 1); + secp256k1_scalar_reduce(r, overflow); + return overflow; +} + +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { + uint128_t t; + VERIFY_CHECK(bit < 256); + bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */ + t = (uint128_t)r->d[0] + (((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F)); + r->d[0] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[1] + (((uint64_t)((bit >> 6) == 1)) << (bit & 0x3F)); + r->d[1] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[2] + (((uint64_t)((bit >> 6) == 2)) << (bit & 0x3F)); + r->d[2] = t & 0xFFFFFFFFFFFFFFFFULL; t >>= 64; + t += (uint128_t)r->d[3] + (((uint64_t)((bit >> 6) == 3)) << (bit & 0x3F)); + r->d[3] = t & 0xFFFFFFFFFFFFFFFFULL; +#ifdef VERIFY + VERIFY_CHECK((t >> 64) == 0); + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { + int over; + r->d[0] = (uint64_t)b32[31] | (uint64_t)b32[30] << 8 | (uint64_t)b32[29] << 16 | (uint64_t)b32[28] << 24 | (uint64_t)b32[27] << 32 | (uint64_t)b32[26] << 40 | (uint64_t)b32[25] << 48 | (uint64_t)b32[24] << 56; + r->d[1] = (uint64_t)b32[23] | (uint64_t)b32[22] << 8 | (uint64_t)b32[21] << 16 | (uint64_t)b32[20] << 24 | (uint64_t)b32[19] << 32 | (uint64_t)b32[18] << 40 | (uint64_t)b32[17] << 48 | (uint64_t)b32[16] << 56; + r->d[2] = (uint64_t)b32[15] | (uint64_t)b32[14] << 8 | (uint64_t)b32[13] << 16 | (uint64_t)b32[12] << 24 | (uint64_t)b32[11] << 32 | (uint64_t)b32[10] << 40 | (uint64_t)b32[9] << 48 | (uint64_t)b32[8] << 56; + r->d[3] = (uint64_t)b32[7] | (uint64_t)b32[6] << 8 | (uint64_t)b32[5] << 16 | (uint64_t)b32[4] << 24 | (uint64_t)b32[3] << 32 | (uint64_t)b32[2] << 40 | (uint64_t)b32[1] << 48 | (uint64_t)b32[0] << 56; + over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); + if (overflow) { + *overflow = over; + } +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { + bin[0] = a->d[3] >> 56; bin[1] = a->d[3] >> 48; bin[2] = a->d[3] >> 40; bin[3] = a->d[3] >> 32; bin[4] = a->d[3] >> 24; bin[5] = a->d[3] >> 16; bin[6] = a->d[3] >> 8; bin[7] = a->d[3]; + bin[8] = a->d[2] >> 56; bin[9] = a->d[2] >> 48; bin[10] = a->d[2] >> 40; bin[11] = a->d[2] >> 32; bin[12] = a->d[2] >> 24; bin[13] = a->d[2] >> 16; bin[14] = a->d[2] >> 8; bin[15] = a->d[2]; + bin[16] = a->d[1] >> 56; bin[17] = a->d[1] >> 48; bin[18] = a->d[1] >> 40; bin[19] = a->d[1] >> 32; bin[20] = a->d[1] >> 24; bin[21] = a->d[1] >> 16; bin[22] = a->d[1] >> 8; bin[23] = a->d[1]; + bin[24] = a->d[0] >> 56; bin[25] = a->d[0] >> 48; bin[26] = a->d[0] >> 40; bin[27] = a->d[0] >> 32; bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { + return (a->d[0] | a->d[1] | a->d[2] | a->d[3]) == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { + uint64_t nonzero = 0xFFFFFFFFFFFFFFFFULL * (secp256k1_scalar_is_zero(a) == 0); + uint128_t t = (uint128_t)(~a->d[0]) + SECP256K1_N_0 + 1; + r->d[0] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[1]) + SECP256K1_N_1; + r->d[1] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[2]) + SECP256K1_N_2; + r->d[2] = t & nonzero; t >>= 64; + t += (uint128_t)(~a->d[3]) + SECP256K1_N_3; + r->d[3] = t & nonzero; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { + return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3]) == 0; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { + int yes = 0; + int no = 0; + no |= (a->d[3] < SECP256K1_N_H_3); + yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; + no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; /* No need for a > check. */ + no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; + yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; + return yes; +} + +static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { + /* If we are flag = 0, mask = 00...00 and this is a no-op; + * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ + uint64_t mask = !flag - 1; + uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1; + uint128_t t = (uint128_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); + r->d[0] = t & nonzero; t >>= 64; + t += (uint128_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); + r->d[1] = t & nonzero; t >>= 64; + t += (uint128_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); + r->d[2] = t & nonzero; t >>= 64; + t += (uint128_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); + r->d[3] = t & nonzero; + return 2 * (mask == 0) - 1; +} + +/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ + +/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd(a,b) { \ + uint64_t tl, th; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c1 += th; /* overflow is handled on the next line */ \ + c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ +} + +/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ +#define muladd_fast(a,b) { \ + uint64_t tl, th; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c1 += th; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK(c1 >= th); \ +} + +/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd2(a,b) { \ + uint64_t tl, th, th2, tl2; \ + { \ + uint128_t t = (uint128_t)a * b; \ + th = t >> 64; /* at most 0xFFFFFFFFFFFFFFFE */ \ + tl = t; \ + } \ + th2 = th + th; /* at most 0xFFFFFFFFFFFFFFFE (in case th was 0x7FFFFFFFFFFFFFFF) */ \ + c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ + tl2 = tl + tl; /* at most 0xFFFFFFFFFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFFFFFFFFFF) */ \ + th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFFFFFFFFFF */ \ + c0 += tl2; /* overflow is handled on the next line */ \ + th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ + c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ + c1 += th2; /* overflow is handled on the next line */ \ + c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ +} + +/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define sumadd(a) { \ + unsigned int over; \ + c0 += (a); /* overflow is handled on the next line */ \ + over = (c0 < (a)) ? 1 : 0; \ + c1 += over; /* overflow is handled on the next line */ \ + c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ +} + +/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ +#define sumadd_fast(a) { \ + c0 += (a); /* overflow is handled on the next line */ \ + c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ + VERIFY_CHECK(c2 == 0); \ +} + +/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. */ +#define extract(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = c2; \ + c2 = 0; \ +} + +/** Extract the lowest 64 bits of (c0,c1,c2) into n, and left shift the number 64 bits. c2 is required to be zero. */ +#define extract_fast(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = 0; \ + VERIFY_CHECK(c2 == 0); \ +} + +static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l) { +#ifdef USE_ASM_X86_64 + /* Reduce 512 bits into 385. */ + uint64_t m0, m1, m2, m3, m4, m5, m6; + uint64_t p0, p1, p2, p3, p4; + uint64_t c; + + __asm__ __volatile__( + /* Preload. */ + "movq 32(%%rsi), %%r11\n" + "movq 40(%%rsi), %%r12\n" + "movq 48(%%rsi), %%r13\n" + "movq 56(%%rsi), %%r14\n" + /* Initialize r8,r9,r10 */ + "movq 0(%%rsi), %%r8\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" + /* (r8,r9) += n0 * c0 */ + "movq %8, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + /* extract m0 */ + "movq %%r8, %q0\n" + "xorq %%r8, %%r8\n" + /* (r9,r10) += l1 */ + "addq 8(%%rsi), %%r9\n" + "adcq $0, %%r10\n" + /* (r9,r10,r8) += n1 * c0 */ + "movq %8, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += n0 * c1 */ + "movq %9, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* extract m1 */ + "movq %%r9, %q1\n" + "xorq %%r9, %%r9\n" + /* (r10,r8,r9) += l2 */ + "addq 16(%%rsi), %%r10\n" + "adcq $0, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += n2 * c0 */ + "movq %8, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += n1 * c1 */ + "movq %9, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += n0 */ + "addq %%r11, %%r10\n" + "adcq $0, %%r8\n" + "adcq $0, %%r9\n" + /* extract m2 */ + "movq %%r10, %q2\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += l3 */ + "addq 24(%%rsi), %%r8\n" + "adcq $0, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += n3 * c0 */ + "movq %8, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += n2 * c1 */ + "movq %9, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += n1 */ + "addq %%r12, %%r8\n" + "adcq $0, %%r9\n" + "adcq $0, %%r10\n" + /* extract m3 */ + "movq %%r8, %q3\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += n3 * c1 */ + "movq %9, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += n2 */ + "addq %%r13, %%r9\n" + "adcq $0, %%r10\n" + "adcq $0, %%r8\n" + /* extract m4 */ + "movq %%r9, %q4\n" + /* (r10,r8) += n3 */ + "addq %%r14, %%r10\n" + "adcq $0, %%r8\n" + /* extract m5 */ + "movq %%r10, %q5\n" + /* extract m6 */ + "movq %%r8, %q6\n" + : "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6) + : "S"(l), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc"); + + /* Reduce 385 bits into 258. */ + __asm__ __volatile__( + /* Preload */ + "movq %q9, %%r11\n" + "movq %q10, %%r12\n" + "movq %q11, %%r13\n" + /* Initialize (r8,r9,r10) */ + "movq %q5, %%r8\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" + /* (r8,r9) += m4 * c0 */ + "movq %12, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + /* extract p0 */ + "movq %%r8, %q0\n" + "xorq %%r8, %%r8\n" + /* (r9,r10) += m1 */ + "addq %q6, %%r9\n" + "adcq $0, %%r10\n" + /* (r9,r10,r8) += m5 * c0 */ + "movq %12, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += m4 * c1 */ + "movq %13, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* extract p1 */ + "movq %%r9, %q1\n" + "xorq %%r9, %%r9\n" + /* (r10,r8,r9) += m2 */ + "addq %q7, %%r10\n" + "adcq $0, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += m6 * c0 */ + "movq %12, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += m5 * c1 */ + "movq %13, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += m4 */ + "addq %%r11, %%r10\n" + "adcq $0, %%r8\n" + "adcq $0, %%r9\n" + /* extract p2 */ + "movq %%r10, %q2\n" + /* (r8,r9) += m3 */ + "addq %q8, %%r8\n" + "adcq $0, %%r9\n" + /* (r8,r9) += m6 * c1 */ + "movq %13, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + /* (r8,r9) += m5 */ + "addq %%r12, %%r8\n" + "adcq $0, %%r9\n" + /* extract p3 */ + "movq %%r8, %q3\n" + /* (r9) += m6 */ + "addq %%r13, %%r9\n" + /* extract p4 */ + "movq %%r9, %q4\n" + : "=&g"(p0), "=&g"(p1), "=&g"(p2), "=g"(p3), "=g"(p4) + : "g"(m0), "g"(m1), "g"(m2), "g"(m3), "g"(m4), "g"(m5), "g"(m6), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "cc"); + + /* Reduce 258 bits into 256. */ + __asm__ __volatile__( + /* Preload */ + "movq %q5, %%r10\n" + /* (rax,rdx) = p4 * c0 */ + "movq %7, %%rax\n" + "mulq %%r10\n" + /* (rax,rdx) += p0 */ + "addq %q1, %%rax\n" + "adcq $0, %%rdx\n" + /* extract r0 */ + "movq %%rax, 0(%q6)\n" + /* Move to (r8,r9) */ + "movq %%rdx, %%r8\n" + "xorq %%r9, %%r9\n" + /* (r8,r9) += p1 */ + "addq %q2, %%r8\n" + "adcq $0, %%r9\n" + /* (r8,r9) += p4 * c1 */ + "movq %8, %%rax\n" + "mulq %%r10\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + /* Extract r1 */ + "movq %%r8, 8(%q6)\n" + "xorq %%r8, %%r8\n" + /* (r9,r8) += p4 */ + "addq %%r10, %%r9\n" + "adcq $0, %%r8\n" + /* (r9,r8) += p2 */ + "addq %q3, %%r9\n" + "adcq $0, %%r8\n" + /* Extract r2 */ + "movq %%r9, 16(%q6)\n" + "xorq %%r9, %%r9\n" + /* (r8,r9) += p3 */ + "addq %q4, %%r8\n" + "adcq $0, %%r9\n" + /* Extract r3 */ + "movq %%r8, 24(%q6)\n" + /* Extract c */ + "movq %%r9, %q0\n" + : "=g"(c) + : "g"(p0), "g"(p1), "g"(p2), "g"(p3), "g"(p4), "D"(r), "n"(SECP256K1_N_C_0), "n"(SECP256K1_N_C_1) + : "rax", "rdx", "r8", "r9", "r10", "cc", "memory"); +#else + uint128_t c; + uint64_t c0, c1, c2; + uint64_t n0 = l[4], n1 = l[5], n2 = l[6], n3 = l[7]; + uint64_t m0, m1, m2, m3, m4, m5; + uint32_t m6; + uint64_t p0, p1, p2, p3; + uint32_t p4; + + /* Reduce 512 bits into 385. */ + /* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */ + c0 = l[0]; c1 = 0; c2 = 0; + muladd_fast(n0, SECP256K1_N_C_0); + extract_fast(m0); + sumadd_fast(l[1]); + muladd(n1, SECP256K1_N_C_0); + muladd(n0, SECP256K1_N_C_1); + extract(m1); + sumadd(l[2]); + muladd(n2, SECP256K1_N_C_0); + muladd(n1, SECP256K1_N_C_1); + sumadd(n0); + extract(m2); + sumadd(l[3]); + muladd(n3, SECP256K1_N_C_0); + muladd(n2, SECP256K1_N_C_1); + sumadd(n1); + extract(m3); + muladd(n3, SECP256K1_N_C_1); + sumadd(n2); + extract(m4); + sumadd_fast(n3); + extract_fast(m5); + VERIFY_CHECK(c0 <= 1); + m6 = c0; + + /* Reduce 385 bits into 258. */ + /* p[0..4] = m[0..3] + m[4..6] * SECP256K1_N_C. */ + c0 = m0; c1 = 0; c2 = 0; + muladd_fast(m4, SECP256K1_N_C_0); + extract_fast(p0); + sumadd_fast(m1); + muladd(m5, SECP256K1_N_C_0); + muladd(m4, SECP256K1_N_C_1); + extract(p1); + sumadd(m2); + muladd(m6, SECP256K1_N_C_0); + muladd(m5, SECP256K1_N_C_1); + sumadd(m4); + extract(p2); + sumadd_fast(m3); + muladd_fast(m6, SECP256K1_N_C_1); + sumadd_fast(m5); + extract_fast(p3); + p4 = c0 + m6; + VERIFY_CHECK(p4 <= 2); + + /* Reduce 258 bits into 256. */ + /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */ + c = p0 + (uint128_t)SECP256K1_N_C_0 * p4; + r->d[0] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p1 + (uint128_t)SECP256K1_N_C_1 * p4; + r->d[1] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p2 + (uint128_t)p4; + r->d[2] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; + c += p3; + r->d[3] = c & 0xFFFFFFFFFFFFFFFFULL; c >>= 64; +#endif + + /* Final reduction of r. */ + secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); +} + +static void secp256k1_scalar_mul_512(uint64_t l[8], const secp256k1_scalar *a, const secp256k1_scalar *b) { +#ifdef USE_ASM_X86_64 + const uint64_t *pb = b->d; + __asm__ __volatile__( + /* Preload */ + "movq 0(%%rdi), %%r15\n" + "movq 8(%%rdi), %%rbx\n" + "movq 16(%%rdi), %%rcx\n" + "movq 0(%%rdx), %%r11\n" + "movq 8(%%rdx), %%r12\n" + "movq 16(%%rdx), %%r13\n" + "movq 24(%%rdx), %%r14\n" + /* (rax,rdx) = a0 * b0 */ + "movq %%r15, %%rax\n" + "mulq %%r11\n" + /* Extract l0 */ + "movq %%rax, 0(%%rsi)\n" + /* (r8,r9,r10) = (rdx) */ + "movq %%rdx, %%r8\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += a0 * b1 */ + "movq %%r15, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += a1 * b0 */ + "movq %%rbx, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* Extract l1 */ + "movq %%r8, 8(%%rsi)\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += a0 * b2 */ + "movq %%r15, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += a1 * b1 */ + "movq %%rbx, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += a2 * b0 */ + "movq %%rcx, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* Extract l2 */ + "movq %%r9, 16(%%rsi)\n" + "xorq %%r9, %%r9\n" + /* (r10,r8,r9) += a0 * b3 */ + "movq %%r15, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* Preload a3 */ + "movq 24(%%rdi), %%r15\n" + /* (r10,r8,r9) += a1 * b2 */ + "movq %%rbx, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += a2 * b1 */ + "movq %%rcx, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += a3 * b0 */ + "movq %%r15, %%rax\n" + "mulq %%r11\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* Extract l3 */ + "movq %%r10, 24(%%rsi)\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += a1 * b3 */ + "movq %%rbx, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += a2 * b2 */ + "movq %%rcx, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += a3 * b1 */ + "movq %%r15, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* Extract l4 */ + "movq %%r8, 32(%%rsi)\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += a2 * b3 */ + "movq %%rcx, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += a3 * b2 */ + "movq %%r15, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* Extract l5 */ + "movq %%r9, 40(%%rsi)\n" + /* (r10,r8) += a3 * b3 */ + "movq %%r15, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + /* Extract l6 */ + "movq %%r10, 48(%%rsi)\n" + /* Extract l7 */ + "movq %%r8, 56(%%rsi)\n" + : "+d"(pb) + : "S"(l), "D"(a->d) + : "rax", "rbx", "rcx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "cc", "memory"); +#else + /* 160 bit accumulator. */ + uint64_t c0 = 0, c1 = 0; + uint32_t c2 = 0; + + /* l[0..7] = a[0..3] * b[0..3]. */ + muladd_fast(a->d[0], b->d[0]); + extract_fast(l[0]); + muladd(a->d[0], b->d[1]); + muladd(a->d[1], b->d[0]); + extract(l[1]); + muladd(a->d[0], b->d[2]); + muladd(a->d[1], b->d[1]); + muladd(a->d[2], b->d[0]); + extract(l[2]); + muladd(a->d[0], b->d[3]); + muladd(a->d[1], b->d[2]); + muladd(a->d[2], b->d[1]); + muladd(a->d[3], b->d[0]); + extract(l[3]); + muladd(a->d[1], b->d[3]); + muladd(a->d[2], b->d[2]); + muladd(a->d[3], b->d[1]); + extract(l[4]); + muladd(a->d[2], b->d[3]); + muladd(a->d[3], b->d[2]); + extract(l[5]); + muladd_fast(a->d[3], b->d[3]); + extract_fast(l[6]); + VERIFY_CHECK(c1 == 0); + l[7] = c0; +#endif +} + +static void secp256k1_scalar_sqr_512(uint64_t l[8], const secp256k1_scalar *a) { +#ifdef USE_ASM_X86_64 + __asm__ __volatile__( + /* Preload */ + "movq 0(%%rdi), %%r11\n" + "movq 8(%%rdi), %%r12\n" + "movq 16(%%rdi), %%r13\n" + "movq 24(%%rdi), %%r14\n" + /* (rax,rdx) = a0 * a0 */ + "movq %%r11, %%rax\n" + "mulq %%r11\n" + /* Extract l0 */ + "movq %%rax, 0(%%rsi)\n" + /* (r8,r9,r10) = (rdx,0) */ + "movq %%rdx, %%r8\n" + "xorq %%r9, %%r9\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += 2 * a0 * a1 */ + "movq %%r11, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* Extract l1 */ + "movq %%r8, 8(%%rsi)\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += 2 * a0 * a2 */ + "movq %%r11, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* (r9,r10,r8) += a1 * a1 */ + "movq %%r12, %%rax\n" + "mulq %%r12\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* Extract l2 */ + "movq %%r9, 16(%%rsi)\n" + "xorq %%r9, %%r9\n" + /* (r10,r8,r9) += 2 * a0 * a3 */ + "movq %%r11, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* (r10,r8,r9) += 2 * a1 * a2 */ + "movq %%r12, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + "adcq $0, %%r9\n" + /* Extract l3 */ + "movq %%r10, 24(%%rsi)\n" + "xorq %%r10, %%r10\n" + /* (r8,r9,r10) += 2 * a1 * a3 */ + "movq %%r12, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* (r8,r9,r10) += a2 * a2 */ + "movq %%r13, %%rax\n" + "mulq %%r13\n" + "addq %%rax, %%r8\n" + "adcq %%rdx, %%r9\n" + "adcq $0, %%r10\n" + /* Extract l4 */ + "movq %%r8, 32(%%rsi)\n" + "xorq %%r8, %%r8\n" + /* (r9,r10,r8) += 2 * a2 * a3 */ + "movq %%r13, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + "addq %%rax, %%r9\n" + "adcq %%rdx, %%r10\n" + "adcq $0, %%r8\n" + /* Extract l5 */ + "movq %%r9, 40(%%rsi)\n" + /* (r10,r8) += a3 * a3 */ + "movq %%r14, %%rax\n" + "mulq %%r14\n" + "addq %%rax, %%r10\n" + "adcq %%rdx, %%r8\n" + /* Extract l6 */ + "movq %%r10, 48(%%rsi)\n" + /* Extract l7 */ + "movq %%r8, 56(%%rsi)\n" + : + : "S"(l), "D"(a->d) + : "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc", "memory"); +#else + /* 160 bit accumulator. */ + uint64_t c0 = 0, c1 = 0; + uint32_t c2 = 0; + + /* l[0..7] = a[0..3] * b[0..3]. */ + muladd_fast(a->d[0], a->d[0]); + extract_fast(l[0]); + muladd2(a->d[0], a->d[1]); + extract(l[1]); + muladd2(a->d[0], a->d[2]); + muladd(a->d[1], a->d[1]); + extract(l[2]); + muladd2(a->d[0], a->d[3]); + muladd2(a->d[1], a->d[2]); + extract(l[3]); + muladd2(a->d[1], a->d[3]); + muladd(a->d[2], a->d[2]); + extract(l[4]); + muladd2(a->d[2], a->d[3]); + extract(l[5]); + muladd_fast(a->d[3], a->d[3]); + extract_fast(l[6]); + VERIFY_CHECK(c1 == 0); + l[7] = c0; +#endif +} + +#undef sumadd +#undef sumadd_fast +#undef muladd +#undef muladd_fast +#undef muladd2 +#undef extract +#undef extract_fast + +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + uint64_t l[8]; + secp256k1_scalar_mul_512(l, a, b); + secp256k1_scalar_reduce_512(r, l); +} + +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { + int ret; + VERIFY_CHECK(n > 0); + VERIFY_CHECK(n < 16); + ret = r->d[0] & ((1 << n) - 1); + r->d[0] = (r->d[0] >> n) + (r->d[1] << (64 - n)); + r->d[1] = (r->d[1] >> n) + (r->d[2] << (64 - n)); + r->d[2] = (r->d[2] >> n) + (r->d[3] << (64 - n)); + r->d[3] = (r->d[3] >> n); + return ret; +} + +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { + uint64_t l[8]; + secp256k1_scalar_sqr_512(l, a); + secp256k1_scalar_reduce_512(r, l); +} + +#ifdef USE_ENDOMORPHISM +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + r1->d[0] = a->d[0]; + r1->d[1] = a->d[1]; + r1->d[2] = 0; + r1->d[3] = 0; + r2->d[0] = a->d[2]; + r2->d[1] = a->d[3]; + r2->d[2] = 0; + r2->d[3] = 0; +} +#endif + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { + return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3])) == 0; +} + +SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { + uint64_t l[8]; + unsigned int shiftlimbs; + unsigned int shiftlow; + unsigned int shifthigh; + VERIFY_CHECK(shift >= 256); + secp256k1_scalar_mul_512(l, a, b); + shiftlimbs = shift >> 6; + shiftlow = shift & 0x3F; + shifthigh = 64 - shiftlow; + r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[1] = shift < 448 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[2] = shift < 384 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[3] = shift < 320 ? (l[3 + shiftlimbs] >> shiftlow) : 0; + secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 6] >> ((shift - 1) & 0x3f)) & 1); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h new file mode 100644 index 00000000..1319664f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32.h @@ -0,0 +1,19 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ + +#include + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef struct { + uint32_t d[8]; +} secp256k1_scalar; + +#define SECP256K1_SCALAR_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {{(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)}} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h new file mode 100644 index 00000000..aae4f35c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_8x32_impl.h @@ -0,0 +1,721 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ + +/* Limbs of the secp256k1 order. */ +#define SECP256K1_N_0 ((uint32_t)0xD0364141UL) +#define SECP256K1_N_1 ((uint32_t)0xBFD25E8CUL) +#define SECP256K1_N_2 ((uint32_t)0xAF48A03BUL) +#define SECP256K1_N_3 ((uint32_t)0xBAAEDCE6UL) +#define SECP256K1_N_4 ((uint32_t)0xFFFFFFFEUL) +#define SECP256K1_N_5 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_6 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_7 ((uint32_t)0xFFFFFFFFUL) + +/* Limbs of 2^256 minus the secp256k1 order. */ +#define SECP256K1_N_C_0 (~SECP256K1_N_0 + 1) +#define SECP256K1_N_C_1 (~SECP256K1_N_1) +#define SECP256K1_N_C_2 (~SECP256K1_N_2) +#define SECP256K1_N_C_3 (~SECP256K1_N_3) +#define SECP256K1_N_C_4 (1) + +/* Limbs of half the secp256k1 order. */ +#define SECP256K1_N_H_0 ((uint32_t)0x681B20A0UL) +#define SECP256K1_N_H_1 ((uint32_t)0xDFE92F46UL) +#define SECP256K1_N_H_2 ((uint32_t)0x57A4501DUL) +#define SECP256K1_N_H_3 ((uint32_t)0x5D576E73UL) +#define SECP256K1_N_H_4 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_5 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_6 ((uint32_t)0xFFFFFFFFUL) +#define SECP256K1_N_H_7 ((uint32_t)0x7FFFFFFFUL) + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { + r->d[0] = 0; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; + r->d[4] = 0; + r->d[5] = 0; + r->d[6] = 0; + r->d[7] = 0; +} + +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { + r->d[0] = v; + r->d[1] = 0; + r->d[2] = 0; + r->d[3] = 0; + r->d[4] = 0; + r->d[5] = 0; + r->d[6] = 0; + r->d[7] = 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK((offset + count - 1) >> 5 == offset >> 5); + return (a->d[offset >> 5] >> (offset & 0x1F)) & ((1 << count) - 1); +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + VERIFY_CHECK(count < 32); + VERIFY_CHECK(offset + count <= 256); + if ((offset + count - 1) >> 5 == offset >> 5) { + return secp256k1_scalar_get_bits(a, offset, count); + } else { + VERIFY_CHECK((offset >> 5) + 1 < 8); + return ((a->d[offset >> 5] >> (offset & 0x1F)) | (a->d[(offset >> 5) + 1] << (32 - (offset & 0x1F)))) & ((((uint32_t)1) << count) - 1); + } +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { + int yes = 0; + int no = 0; + no |= (a->d[7] < SECP256K1_N_7); /* No need for a > check. */ + no |= (a->d[6] < SECP256K1_N_6); /* No need for a > check. */ + no |= (a->d[5] < SECP256K1_N_5); /* No need for a > check. */ + no |= (a->d[4] < SECP256K1_N_4); + yes |= (a->d[4] > SECP256K1_N_4) & ~no; + no |= (a->d[3] < SECP256K1_N_3) & ~yes; + yes |= (a->d[3] > SECP256K1_N_3) & ~no; + no |= (a->d[2] < SECP256K1_N_2) & ~yes; + yes |= (a->d[2] > SECP256K1_N_2) & ~no; + no |= (a->d[1] < SECP256K1_N_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_1) & ~no; + yes |= (a->d[0] >= SECP256K1_N_0) & ~no; + return yes; +} + +SECP256K1_INLINE static int secp256k1_scalar_reduce(secp256k1_scalar *r, uint32_t overflow) { + uint64_t t; + VERIFY_CHECK(overflow <= 1); + t = (uint64_t)r->d[0] + overflow * SECP256K1_N_C_0; + r->d[0] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[1] + overflow * SECP256K1_N_C_1; + r->d[1] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[2] + overflow * SECP256K1_N_C_2; + r->d[2] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[3] + overflow * SECP256K1_N_C_3; + r->d[3] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[4] + overflow * SECP256K1_N_C_4; + r->d[4] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[5]; + r->d[5] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[6]; + r->d[6] = t & 0xFFFFFFFFUL; t >>= 32; + t += (uint64_t)r->d[7]; + r->d[7] = t & 0xFFFFFFFFUL; + return overflow; +} + +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + int overflow; + uint64_t t = (uint64_t)a->d[0] + b->d[0]; + r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[1] + b->d[1]; + r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[2] + b->d[2]; + r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[3] + b->d[3]; + r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[4] + b->d[4]; + r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[5] + b->d[5]; + r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[6] + b->d[6]; + r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)a->d[7] + b->d[7]; + r->d[7] = t & 0xFFFFFFFFULL; t >>= 32; + overflow = t + secp256k1_scalar_check_overflow(r); + VERIFY_CHECK(overflow == 0 || overflow == 1); + secp256k1_scalar_reduce(r, overflow); + return overflow; +} + +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { + uint64_t t; + VERIFY_CHECK(bit < 256); + bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */ + t = (uint64_t)r->d[0] + (((uint32_t)((bit >> 5) == 0)) << (bit & 0x1F)); + r->d[0] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[1] + (((uint32_t)((bit >> 5) == 1)) << (bit & 0x1F)); + r->d[1] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[2] + (((uint32_t)((bit >> 5) == 2)) << (bit & 0x1F)); + r->d[2] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[3] + (((uint32_t)((bit >> 5) == 3)) << (bit & 0x1F)); + r->d[3] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[4] + (((uint32_t)((bit >> 5) == 4)) << (bit & 0x1F)); + r->d[4] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[5] + (((uint32_t)((bit >> 5) == 5)) << (bit & 0x1F)); + r->d[5] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[6] + (((uint32_t)((bit >> 5) == 6)) << (bit & 0x1F)); + r->d[6] = t & 0xFFFFFFFFULL; t >>= 32; + t += (uint64_t)r->d[7] + (((uint32_t)((bit >> 5) == 7)) << (bit & 0x1F)); + r->d[7] = t & 0xFFFFFFFFULL; +#ifdef VERIFY + VERIFY_CHECK((t >> 32) == 0); + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { + int over; + r->d[0] = (uint32_t)b32[31] | (uint32_t)b32[30] << 8 | (uint32_t)b32[29] << 16 | (uint32_t)b32[28] << 24; + r->d[1] = (uint32_t)b32[27] | (uint32_t)b32[26] << 8 | (uint32_t)b32[25] << 16 | (uint32_t)b32[24] << 24; + r->d[2] = (uint32_t)b32[23] | (uint32_t)b32[22] << 8 | (uint32_t)b32[21] << 16 | (uint32_t)b32[20] << 24; + r->d[3] = (uint32_t)b32[19] | (uint32_t)b32[18] << 8 | (uint32_t)b32[17] << 16 | (uint32_t)b32[16] << 24; + r->d[4] = (uint32_t)b32[15] | (uint32_t)b32[14] << 8 | (uint32_t)b32[13] << 16 | (uint32_t)b32[12] << 24; + r->d[5] = (uint32_t)b32[11] | (uint32_t)b32[10] << 8 | (uint32_t)b32[9] << 16 | (uint32_t)b32[8] << 24; + r->d[6] = (uint32_t)b32[7] | (uint32_t)b32[6] << 8 | (uint32_t)b32[5] << 16 | (uint32_t)b32[4] << 24; + r->d[7] = (uint32_t)b32[3] | (uint32_t)b32[2] << 8 | (uint32_t)b32[1] << 16 | (uint32_t)b32[0] << 24; + over = secp256k1_scalar_reduce(r, secp256k1_scalar_check_overflow(r)); + if (overflow) { + *overflow = over; + } +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { + bin[0] = a->d[7] >> 24; bin[1] = a->d[7] >> 16; bin[2] = a->d[7] >> 8; bin[3] = a->d[7]; + bin[4] = a->d[6] >> 24; bin[5] = a->d[6] >> 16; bin[6] = a->d[6] >> 8; bin[7] = a->d[6]; + bin[8] = a->d[5] >> 24; bin[9] = a->d[5] >> 16; bin[10] = a->d[5] >> 8; bin[11] = a->d[5]; + bin[12] = a->d[4] >> 24; bin[13] = a->d[4] >> 16; bin[14] = a->d[4] >> 8; bin[15] = a->d[4]; + bin[16] = a->d[3] >> 24; bin[17] = a->d[3] >> 16; bin[18] = a->d[3] >> 8; bin[19] = a->d[3]; + bin[20] = a->d[2] >> 24; bin[21] = a->d[2] >> 16; bin[22] = a->d[2] >> 8; bin[23] = a->d[2]; + bin[24] = a->d[1] >> 24; bin[25] = a->d[1] >> 16; bin[26] = a->d[1] >> 8; bin[27] = a->d[1]; + bin[28] = a->d[0] >> 24; bin[29] = a->d[0] >> 16; bin[30] = a->d[0] >> 8; bin[31] = a->d[0]; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { + return (a->d[0] | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { + uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(a) == 0); + uint64_t t = (uint64_t)(~a->d[0]) + SECP256K1_N_0 + 1; + r->d[0] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[1]) + SECP256K1_N_1; + r->d[1] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[2]) + SECP256K1_N_2; + r->d[2] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[3]) + SECP256K1_N_3; + r->d[3] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[4]) + SECP256K1_N_4; + r->d[4] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[5]) + SECP256K1_N_5; + r->d[5] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[6]) + SECP256K1_N_6; + r->d[6] = t & nonzero; t >>= 32; + t += (uint64_t)(~a->d[7]) + SECP256K1_N_7; + r->d[7] = t & nonzero; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { + return ((a->d[0] ^ 1) | a->d[1] | a->d[2] | a->d[3] | a->d[4] | a->d[5] | a->d[6] | a->d[7]) == 0; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { + int yes = 0; + int no = 0; + no |= (a->d[7] < SECP256K1_N_H_7); + yes |= (a->d[7] > SECP256K1_N_H_7) & ~no; + no |= (a->d[6] < SECP256K1_N_H_6) & ~yes; /* No need for a > check. */ + no |= (a->d[5] < SECP256K1_N_H_5) & ~yes; /* No need for a > check. */ + no |= (a->d[4] < SECP256K1_N_H_4) & ~yes; /* No need for a > check. */ + no |= (a->d[3] < SECP256K1_N_H_3) & ~yes; + yes |= (a->d[3] > SECP256K1_N_H_3) & ~no; + no |= (a->d[2] < SECP256K1_N_H_2) & ~yes; + yes |= (a->d[2] > SECP256K1_N_H_2) & ~no; + no |= (a->d[1] < SECP256K1_N_H_1) & ~yes; + yes |= (a->d[1] > SECP256K1_N_H_1) & ~no; + yes |= (a->d[0] > SECP256K1_N_H_0) & ~no; + return yes; +} + +static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { + /* If we are flag = 0, mask = 00...00 and this is a no-op; + * if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */ + uint32_t mask = !flag - 1; + uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0); + uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask); + r->d[0] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[1] ^ mask) + (SECP256K1_N_1 & mask); + r->d[1] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[2] ^ mask) + (SECP256K1_N_2 & mask); + r->d[2] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[3] ^ mask) + (SECP256K1_N_3 & mask); + r->d[3] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[4] ^ mask) + (SECP256K1_N_4 & mask); + r->d[4] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[5] ^ mask) + (SECP256K1_N_5 & mask); + r->d[5] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[6] ^ mask) + (SECP256K1_N_6 & mask); + r->d[6] = t & nonzero; t >>= 32; + t += (uint64_t)(r->d[7] ^ mask) + (SECP256K1_N_7 & mask); + r->d[7] = t & nonzero; + return 2 * (mask == 0) - 1; +} + + +/* Inspired by the macros in OpenSSL's crypto/bn/asm/x86_64-gcc.c. */ + +/** Add a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd(a,b) { \ + uint32_t tl, th; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c1 += th; /* overflow is handled on the next line */ \ + c2 += (c1 < th) ? 1 : 0; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK((c1 >= th) || (c2 != 0)); \ +} + +/** Add a*b to the number defined by (c0,c1). c1 must never overflow. */ +#define muladd_fast(a,b) { \ + uint32_t tl, th; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + c0 += tl; /* overflow is handled on the next line */ \ + th += (c0 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c1 += th; /* never overflows by contract (verified in the next line) */ \ + VERIFY_CHECK(c1 >= th); \ +} + +/** Add 2*a*b to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define muladd2(a,b) { \ + uint32_t tl, th, th2, tl2; \ + { \ + uint64_t t = (uint64_t)a * b; \ + th = t >> 32; /* at most 0xFFFFFFFE */ \ + tl = t; \ + } \ + th2 = th + th; /* at most 0xFFFFFFFE (in case th was 0x7FFFFFFF) */ \ + c2 += (th2 < th) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((th2 >= th) || (c2 != 0)); \ + tl2 = tl + tl; /* at most 0xFFFFFFFE (in case the lowest 63 bits of tl were 0x7FFFFFFF) */ \ + th2 += (tl2 < tl) ? 1 : 0; /* at most 0xFFFFFFFF */ \ + c0 += tl2; /* overflow is handled on the next line */ \ + th2 += (c0 < tl2) ? 1 : 0; /* second overflow is handled on the next line */ \ + c2 += (c0 < tl2) & (th2 == 0); /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c0 >= tl2) || (th2 != 0) || (c2 != 0)); \ + c1 += th2; /* overflow is handled on the next line */ \ + c2 += (c1 < th2) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 >= th2) || (c2 != 0)); \ +} + +/** Add a to the number defined by (c0,c1,c2). c2 must never overflow. */ +#define sumadd(a) { \ + unsigned int over; \ + c0 += (a); /* overflow is handled on the next line */ \ + over = (c0 < (a)) ? 1 : 0; \ + c1 += over; /* overflow is handled on the next line */ \ + c2 += (c1 < over) ? 1 : 0; /* never overflows by contract */ \ +} + +/** Add a to the number defined by (c0,c1). c1 must never overflow, c2 must be zero. */ +#define sumadd_fast(a) { \ + c0 += (a); /* overflow is handled on the next line */ \ + c1 += (c0 < (a)) ? 1 : 0; /* never overflows by contract (verified the next line) */ \ + VERIFY_CHECK((c1 != 0) | (c0 >= (a))); \ + VERIFY_CHECK(c2 == 0); \ +} + +/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. */ +#define extract(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = c2; \ + c2 = 0; \ +} + +/** Extract the lowest 32 bits of (c0,c1,c2) into n, and left shift the number 32 bits. c2 is required to be zero. */ +#define extract_fast(n) { \ + (n) = c0; \ + c0 = c1; \ + c1 = 0; \ + VERIFY_CHECK(c2 == 0); \ +} + +static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint32_t *l) { + uint64_t c; + uint32_t n0 = l[8], n1 = l[9], n2 = l[10], n3 = l[11], n4 = l[12], n5 = l[13], n6 = l[14], n7 = l[15]; + uint32_t m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12; + uint32_t p0, p1, p2, p3, p4, p5, p6, p7, p8; + + /* 96 bit accumulator. */ + uint32_t c0, c1, c2; + + /* Reduce 512 bits into 385. */ + /* m[0..12] = l[0..7] + n[0..7] * SECP256K1_N_C. */ + c0 = l[0]; c1 = 0; c2 = 0; + muladd_fast(n0, SECP256K1_N_C_0); + extract_fast(m0); + sumadd_fast(l[1]); + muladd(n1, SECP256K1_N_C_0); + muladd(n0, SECP256K1_N_C_1); + extract(m1); + sumadd(l[2]); + muladd(n2, SECP256K1_N_C_0); + muladd(n1, SECP256K1_N_C_1); + muladd(n0, SECP256K1_N_C_2); + extract(m2); + sumadd(l[3]); + muladd(n3, SECP256K1_N_C_0); + muladd(n2, SECP256K1_N_C_1); + muladd(n1, SECP256K1_N_C_2); + muladd(n0, SECP256K1_N_C_3); + extract(m3); + sumadd(l[4]); + muladd(n4, SECP256K1_N_C_0); + muladd(n3, SECP256K1_N_C_1); + muladd(n2, SECP256K1_N_C_2); + muladd(n1, SECP256K1_N_C_3); + sumadd(n0); + extract(m4); + sumadd(l[5]); + muladd(n5, SECP256K1_N_C_0); + muladd(n4, SECP256K1_N_C_1); + muladd(n3, SECP256K1_N_C_2); + muladd(n2, SECP256K1_N_C_3); + sumadd(n1); + extract(m5); + sumadd(l[6]); + muladd(n6, SECP256K1_N_C_0); + muladd(n5, SECP256K1_N_C_1); + muladd(n4, SECP256K1_N_C_2); + muladd(n3, SECP256K1_N_C_3); + sumadd(n2); + extract(m6); + sumadd(l[7]); + muladd(n7, SECP256K1_N_C_0); + muladd(n6, SECP256K1_N_C_1); + muladd(n5, SECP256K1_N_C_2); + muladd(n4, SECP256K1_N_C_3); + sumadd(n3); + extract(m7); + muladd(n7, SECP256K1_N_C_1); + muladd(n6, SECP256K1_N_C_2); + muladd(n5, SECP256K1_N_C_3); + sumadd(n4); + extract(m8); + muladd(n7, SECP256K1_N_C_2); + muladd(n6, SECP256K1_N_C_3); + sumadd(n5); + extract(m9); + muladd(n7, SECP256K1_N_C_3); + sumadd(n6); + extract(m10); + sumadd_fast(n7); + extract_fast(m11); + VERIFY_CHECK(c0 <= 1); + m12 = c0; + + /* Reduce 385 bits into 258. */ + /* p[0..8] = m[0..7] + m[8..12] * SECP256K1_N_C. */ + c0 = m0; c1 = 0; c2 = 0; + muladd_fast(m8, SECP256K1_N_C_0); + extract_fast(p0); + sumadd_fast(m1); + muladd(m9, SECP256K1_N_C_0); + muladd(m8, SECP256K1_N_C_1); + extract(p1); + sumadd(m2); + muladd(m10, SECP256K1_N_C_0); + muladd(m9, SECP256K1_N_C_1); + muladd(m8, SECP256K1_N_C_2); + extract(p2); + sumadd(m3); + muladd(m11, SECP256K1_N_C_0); + muladd(m10, SECP256K1_N_C_1); + muladd(m9, SECP256K1_N_C_2); + muladd(m8, SECP256K1_N_C_3); + extract(p3); + sumadd(m4); + muladd(m12, SECP256K1_N_C_0); + muladd(m11, SECP256K1_N_C_1); + muladd(m10, SECP256K1_N_C_2); + muladd(m9, SECP256K1_N_C_3); + sumadd(m8); + extract(p4); + sumadd(m5); + muladd(m12, SECP256K1_N_C_1); + muladd(m11, SECP256K1_N_C_2); + muladd(m10, SECP256K1_N_C_3); + sumadd(m9); + extract(p5); + sumadd(m6); + muladd(m12, SECP256K1_N_C_2); + muladd(m11, SECP256K1_N_C_3); + sumadd(m10); + extract(p6); + sumadd_fast(m7); + muladd_fast(m12, SECP256K1_N_C_3); + sumadd_fast(m11); + extract_fast(p7); + p8 = c0 + m12; + VERIFY_CHECK(p8 <= 2); + + /* Reduce 258 bits into 256. */ + /* r[0..7] = p[0..7] + p[8] * SECP256K1_N_C. */ + c = p0 + (uint64_t)SECP256K1_N_C_0 * p8; + r->d[0] = c & 0xFFFFFFFFUL; c >>= 32; + c += p1 + (uint64_t)SECP256K1_N_C_1 * p8; + r->d[1] = c & 0xFFFFFFFFUL; c >>= 32; + c += p2 + (uint64_t)SECP256K1_N_C_2 * p8; + r->d[2] = c & 0xFFFFFFFFUL; c >>= 32; + c += p3 + (uint64_t)SECP256K1_N_C_3 * p8; + r->d[3] = c & 0xFFFFFFFFUL; c >>= 32; + c += p4 + (uint64_t)p8; + r->d[4] = c & 0xFFFFFFFFUL; c >>= 32; + c += p5; + r->d[5] = c & 0xFFFFFFFFUL; c >>= 32; + c += p6; + r->d[6] = c & 0xFFFFFFFFUL; c >>= 32; + c += p7; + r->d[7] = c & 0xFFFFFFFFUL; c >>= 32; + + /* Final reduction of r. */ + secp256k1_scalar_reduce(r, c + secp256k1_scalar_check_overflow(r)); +} + +static void secp256k1_scalar_mul_512(uint32_t *l, const secp256k1_scalar *a, const secp256k1_scalar *b) { + /* 96 bit accumulator. */ + uint32_t c0 = 0, c1 = 0, c2 = 0; + + /* l[0..15] = a[0..7] * b[0..7]. */ + muladd_fast(a->d[0], b->d[0]); + extract_fast(l[0]); + muladd(a->d[0], b->d[1]); + muladd(a->d[1], b->d[0]); + extract(l[1]); + muladd(a->d[0], b->d[2]); + muladd(a->d[1], b->d[1]); + muladd(a->d[2], b->d[0]); + extract(l[2]); + muladd(a->d[0], b->d[3]); + muladd(a->d[1], b->d[2]); + muladd(a->d[2], b->d[1]); + muladd(a->d[3], b->d[0]); + extract(l[3]); + muladd(a->d[0], b->d[4]); + muladd(a->d[1], b->d[3]); + muladd(a->d[2], b->d[2]); + muladd(a->d[3], b->d[1]); + muladd(a->d[4], b->d[0]); + extract(l[4]); + muladd(a->d[0], b->d[5]); + muladd(a->d[1], b->d[4]); + muladd(a->d[2], b->d[3]); + muladd(a->d[3], b->d[2]); + muladd(a->d[4], b->d[1]); + muladd(a->d[5], b->d[0]); + extract(l[5]); + muladd(a->d[0], b->d[6]); + muladd(a->d[1], b->d[5]); + muladd(a->d[2], b->d[4]); + muladd(a->d[3], b->d[3]); + muladd(a->d[4], b->d[2]); + muladd(a->d[5], b->d[1]); + muladd(a->d[6], b->d[0]); + extract(l[6]); + muladd(a->d[0], b->d[7]); + muladd(a->d[1], b->d[6]); + muladd(a->d[2], b->d[5]); + muladd(a->d[3], b->d[4]); + muladd(a->d[4], b->d[3]); + muladd(a->d[5], b->d[2]); + muladd(a->d[6], b->d[1]); + muladd(a->d[7], b->d[0]); + extract(l[7]); + muladd(a->d[1], b->d[7]); + muladd(a->d[2], b->d[6]); + muladd(a->d[3], b->d[5]); + muladd(a->d[4], b->d[4]); + muladd(a->d[5], b->d[3]); + muladd(a->d[6], b->d[2]); + muladd(a->d[7], b->d[1]); + extract(l[8]); + muladd(a->d[2], b->d[7]); + muladd(a->d[3], b->d[6]); + muladd(a->d[4], b->d[5]); + muladd(a->d[5], b->d[4]); + muladd(a->d[6], b->d[3]); + muladd(a->d[7], b->d[2]); + extract(l[9]); + muladd(a->d[3], b->d[7]); + muladd(a->d[4], b->d[6]); + muladd(a->d[5], b->d[5]); + muladd(a->d[6], b->d[4]); + muladd(a->d[7], b->d[3]); + extract(l[10]); + muladd(a->d[4], b->d[7]); + muladd(a->d[5], b->d[6]); + muladd(a->d[6], b->d[5]); + muladd(a->d[7], b->d[4]); + extract(l[11]); + muladd(a->d[5], b->d[7]); + muladd(a->d[6], b->d[6]); + muladd(a->d[7], b->d[5]); + extract(l[12]); + muladd(a->d[6], b->d[7]); + muladd(a->d[7], b->d[6]); + extract(l[13]); + muladd_fast(a->d[7], b->d[7]); + extract_fast(l[14]); + VERIFY_CHECK(c1 == 0); + l[15] = c0; +} + +static void secp256k1_scalar_sqr_512(uint32_t *l, const secp256k1_scalar *a) { + /* 96 bit accumulator. */ + uint32_t c0 = 0, c1 = 0, c2 = 0; + + /* l[0..15] = a[0..7]^2. */ + muladd_fast(a->d[0], a->d[0]); + extract_fast(l[0]); + muladd2(a->d[0], a->d[1]); + extract(l[1]); + muladd2(a->d[0], a->d[2]); + muladd(a->d[1], a->d[1]); + extract(l[2]); + muladd2(a->d[0], a->d[3]); + muladd2(a->d[1], a->d[2]); + extract(l[3]); + muladd2(a->d[0], a->d[4]); + muladd2(a->d[1], a->d[3]); + muladd(a->d[2], a->d[2]); + extract(l[4]); + muladd2(a->d[0], a->d[5]); + muladd2(a->d[1], a->d[4]); + muladd2(a->d[2], a->d[3]); + extract(l[5]); + muladd2(a->d[0], a->d[6]); + muladd2(a->d[1], a->d[5]); + muladd2(a->d[2], a->d[4]); + muladd(a->d[3], a->d[3]); + extract(l[6]); + muladd2(a->d[0], a->d[7]); + muladd2(a->d[1], a->d[6]); + muladd2(a->d[2], a->d[5]); + muladd2(a->d[3], a->d[4]); + extract(l[7]); + muladd2(a->d[1], a->d[7]); + muladd2(a->d[2], a->d[6]); + muladd2(a->d[3], a->d[5]); + muladd(a->d[4], a->d[4]); + extract(l[8]); + muladd2(a->d[2], a->d[7]); + muladd2(a->d[3], a->d[6]); + muladd2(a->d[4], a->d[5]); + extract(l[9]); + muladd2(a->d[3], a->d[7]); + muladd2(a->d[4], a->d[6]); + muladd(a->d[5], a->d[5]); + extract(l[10]); + muladd2(a->d[4], a->d[7]); + muladd2(a->d[5], a->d[6]); + extract(l[11]); + muladd2(a->d[5], a->d[7]); + muladd(a->d[6], a->d[6]); + extract(l[12]); + muladd2(a->d[6], a->d[7]); + extract(l[13]); + muladd_fast(a->d[7], a->d[7]); + extract_fast(l[14]); + VERIFY_CHECK(c1 == 0); + l[15] = c0; +} + +#undef sumadd +#undef sumadd_fast +#undef muladd +#undef muladd_fast +#undef muladd2 +#undef extract +#undef extract_fast + +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + uint32_t l[16]; + secp256k1_scalar_mul_512(l, a, b); + secp256k1_scalar_reduce_512(r, l); +} + +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { + int ret; + VERIFY_CHECK(n > 0); + VERIFY_CHECK(n < 16); + ret = r->d[0] & ((1 << n) - 1); + r->d[0] = (r->d[0] >> n) + (r->d[1] << (32 - n)); + r->d[1] = (r->d[1] >> n) + (r->d[2] << (32 - n)); + r->d[2] = (r->d[2] >> n) + (r->d[3] << (32 - n)); + r->d[3] = (r->d[3] >> n) + (r->d[4] << (32 - n)); + r->d[4] = (r->d[4] >> n) + (r->d[5] << (32 - n)); + r->d[5] = (r->d[5] >> n) + (r->d[6] << (32 - n)); + r->d[6] = (r->d[6] >> n) + (r->d[7] << (32 - n)); + r->d[7] = (r->d[7] >> n); + return ret; +} + +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { + uint32_t l[16]; + secp256k1_scalar_sqr_512(l, a); + secp256k1_scalar_reduce_512(r, l); +} + +#ifdef USE_ENDOMORPHISM +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + r1->d[0] = a->d[0]; + r1->d[1] = a->d[1]; + r1->d[2] = a->d[2]; + r1->d[3] = a->d[3]; + r1->d[4] = 0; + r1->d[5] = 0; + r1->d[6] = 0; + r1->d[7] = 0; + r2->d[0] = a->d[4]; + r2->d[1] = a->d[5]; + r2->d[2] = a->d[6]; + r2->d[3] = a->d[7]; + r2->d[4] = 0; + r2->d[5] = 0; + r2->d[6] = 0; + r2->d[7] = 0; +} +#endif + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { + return ((a->d[0] ^ b->d[0]) | (a->d[1] ^ b->d[1]) | (a->d[2] ^ b->d[2]) | (a->d[3] ^ b->d[3]) | (a->d[4] ^ b->d[4]) | (a->d[5] ^ b->d[5]) | (a->d[6] ^ b->d[6]) | (a->d[7] ^ b->d[7])) == 0; +} + +SECP256K1_INLINE static void secp256k1_scalar_mul_shift_var(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b, unsigned int shift) { + uint32_t l[16]; + unsigned int shiftlimbs; + unsigned int shiftlow; + unsigned int shifthigh; + VERIFY_CHECK(shift >= 256); + secp256k1_scalar_mul_512(l, a, b); + shiftlimbs = shift >> 5; + shiftlow = shift & 0x1F; + shifthigh = 32 - shiftlow; + r->d[0] = shift < 512 ? (l[0 + shiftlimbs] >> shiftlow | (shift < 480 && shiftlow ? (l[1 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[1] = shift < 480 ? (l[1 + shiftlimbs] >> shiftlow | (shift < 448 && shiftlow ? (l[2 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[2] = shift < 448 ? (l[2 + shiftlimbs] >> shiftlow | (shift < 416 && shiftlow ? (l[3 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[3] = shift < 416 ? (l[3 + shiftlimbs] >> shiftlow | (shift < 384 && shiftlow ? (l[4 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[4] = shift < 384 ? (l[4 + shiftlimbs] >> shiftlow | (shift < 352 && shiftlow ? (l[5 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[5] = shift < 352 ? (l[5 + shiftlimbs] >> shiftlow | (shift < 320 && shiftlow ? (l[6 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[6] = shift < 320 ? (l[6 + shiftlimbs] >> shiftlow | (shift < 288 && shiftlow ? (l[7 + shiftlimbs] << shifthigh) : 0)) : 0; + r->d[7] = shift < 288 ? (l[7 + shiftlimbs] >> shiftlow) : 0; + secp256k1_scalar_cadd_bit(r, 0, (l[(shift - 1) >> 5] >> ((shift - 1) & 0x1f)) & 1); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h new file mode 100644 index 00000000..f5b23764 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_impl.h @@ -0,0 +1,370 @@ +/********************************************************************** + * Copyright (c) 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_IMPL_H_ +#define _SECP256K1_SCALAR_IMPL_H_ + +#include "group.h" +#include "scalar.h" + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#if defined(EXHAUSTIVE_TEST_ORDER) +#include "scalar_low_impl.h" +#elif defined(USE_SCALAR_4X64) +#include "scalar_4x64_impl.h" +#elif defined(USE_SCALAR_8X32) +#include "scalar_8x32_impl.h" +#else +#error "Please select scalar implementation" +#endif + +#ifndef USE_NUM_NONE +static void secp256k1_scalar_get_num(secp256k1_num *r, const secp256k1_scalar *a) { + unsigned char c[32]; + secp256k1_scalar_get_b32(c, a); + secp256k1_num_set_bin(r, c, 32); +} + +/** secp256k1 curve order, see secp256k1_ecdsa_const_order_as_fe in ecdsa_impl.h */ +static void secp256k1_scalar_order_get_num(secp256k1_num *r) { +#if defined(EXHAUSTIVE_TEST_ORDER) + static const unsigned char order[32] = { + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,EXHAUSTIVE_TEST_ORDER + }; +#else + static const unsigned char order[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 + }; +#endif + secp256k1_num_set_bin(r, order, 32); +} +#endif + +static void secp256k1_scalar_inverse(secp256k1_scalar *r, const secp256k1_scalar *x) { +#if defined(EXHAUSTIVE_TEST_ORDER) + int i; + *r = 0; + for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) + if ((i * *x) % EXHAUSTIVE_TEST_ORDER == 1) + *r = i; + /* If this VERIFY_CHECK triggers we were given a noninvertible scalar (and thus + * have a composite group order; fix it in exhaustive_tests.c). */ + VERIFY_CHECK(*r != 0); +} +#else + secp256k1_scalar *t; + int i; + /* First compute x ^ (2^N - 1) for some values of N. */ + secp256k1_scalar x2, x3, x4, x6, x7, x8, x15, x30, x60, x120, x127; + + secp256k1_scalar_sqr(&x2, x); + secp256k1_scalar_mul(&x2, &x2, x); + + secp256k1_scalar_sqr(&x3, &x2); + secp256k1_scalar_mul(&x3, &x3, x); + + secp256k1_scalar_sqr(&x4, &x3); + secp256k1_scalar_mul(&x4, &x4, x); + + secp256k1_scalar_sqr(&x6, &x4); + secp256k1_scalar_sqr(&x6, &x6); + secp256k1_scalar_mul(&x6, &x6, &x2); + + secp256k1_scalar_sqr(&x7, &x6); + secp256k1_scalar_mul(&x7, &x7, x); + + secp256k1_scalar_sqr(&x8, &x7); + secp256k1_scalar_mul(&x8, &x8, x); + + secp256k1_scalar_sqr(&x15, &x8); + for (i = 0; i < 6; i++) { + secp256k1_scalar_sqr(&x15, &x15); + } + secp256k1_scalar_mul(&x15, &x15, &x7); + + secp256k1_scalar_sqr(&x30, &x15); + for (i = 0; i < 14; i++) { + secp256k1_scalar_sqr(&x30, &x30); + } + secp256k1_scalar_mul(&x30, &x30, &x15); + + secp256k1_scalar_sqr(&x60, &x30); + for (i = 0; i < 29; i++) { + secp256k1_scalar_sqr(&x60, &x60); + } + secp256k1_scalar_mul(&x60, &x60, &x30); + + secp256k1_scalar_sqr(&x120, &x60); + for (i = 0; i < 59; i++) { + secp256k1_scalar_sqr(&x120, &x120); + } + secp256k1_scalar_mul(&x120, &x120, &x60); + + secp256k1_scalar_sqr(&x127, &x120); + for (i = 0; i < 6; i++) { + secp256k1_scalar_sqr(&x127, &x127); + } + secp256k1_scalar_mul(&x127, &x127, &x7); + + /* Then accumulate the final result (t starts at x127). */ + t = &x127; + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 3; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 5; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 4; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 5; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x4); /* 1111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 4; i++) { /* 000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 10; i++) { /* 0000000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 4; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x3); /* 111 */ + for (i = 0; i < 9; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x8); /* 11111111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 5; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x4); /* 1111 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 5; i++) { /* 000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 4; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 2; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 8; i++) { /* 000000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 3; i++) { /* 0 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, &x2); /* 11 */ + for (i = 0; i < 3; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 6; i++) { /* 00000 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(t, t, x); /* 1 */ + for (i = 0; i < 8; i++) { /* 00 */ + secp256k1_scalar_sqr(t, t); + } + secp256k1_scalar_mul(r, t, &x6); /* 111111 */ +} + +SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { + return !(a->d[0] & 1); +} +#endif + +static void secp256k1_scalar_inverse_var(secp256k1_scalar *r, const secp256k1_scalar *x) { +#if defined(USE_SCALAR_INV_BUILTIN) + secp256k1_scalar_inverse(r, x); +#elif defined(USE_SCALAR_INV_NUM) + unsigned char b[32]; + secp256k1_num n, m; + secp256k1_scalar t = *x; + secp256k1_scalar_get_b32(b, &t); + secp256k1_num_set_bin(&n, b, 32); + secp256k1_scalar_order_get_num(&m); + secp256k1_num_mod_inverse(&n, &n, &m); + secp256k1_num_get_bin(b, 32, &n); + secp256k1_scalar_set_b32(r, b, NULL); + /* Verify that the inverse was computed correctly, without GMP code. */ + secp256k1_scalar_mul(&t, &t, r); + CHECK(secp256k1_scalar_is_one(&t)); +#else +#error "Please select scalar inverse implementation" +#endif +} + +#ifdef USE_ENDOMORPHISM +#if defined(EXHAUSTIVE_TEST_ORDER) +/** + * Find k1 and k2 given k, such that k1 + k2 * lambda == k mod n; unlike in the + * full case we don't bother making k1 and k2 be small, we just want them to be + * nontrivial to get full test coverage for the exhaustive tests. We therefore + * (arbitrarily) set k2 = k + 5 and k1 = k - k2 * lambda. + */ +static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + *r2 = (*a + 5) % EXHAUSTIVE_TEST_ORDER; + *r1 = (*a + (EXHAUSTIVE_TEST_ORDER - *r2) * EXHAUSTIVE_TEST_LAMBDA) % EXHAUSTIVE_TEST_ORDER; +} +#else +/** + * The Secp256k1 curve has an endomorphism, where lambda * (x, y) = (beta * x, y), where + * lambda is {0x53,0x63,0xad,0x4c,0xc0,0x5c,0x30,0xe0,0xa5,0x26,0x1c,0x02,0x88,0x12,0x64,0x5a, + * 0x12,0x2e,0x22,0xea,0x20,0x81,0x66,0x78,0xdf,0x02,0x96,0x7c,0x1b,0x23,0xbd,0x72} + * + * "Guide to Elliptic Curve Cryptography" (Hankerson, Menezes, Vanstone) gives an algorithm + * (algorithm 3.74) to find k1 and k2 given k, such that k1 + k2 * lambda == k mod n, and k1 + * and k2 have a small size. + * It relies on constants a1, b1, a2, b2. These constants for the value of lambda above are: + * + * - a1 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} + * - b1 = -{0xe4,0x43,0x7e,0xd6,0x01,0x0e,0x88,0x28,0x6f,0x54,0x7f,0xa9,0x0a,0xbf,0xe4,0xc3} + * - a2 = {0x01,0x14,0xca,0x50,0xf7,0xa8,0xe2,0xf3,0xf6,0x57,0xc1,0x10,0x8d,0x9d,0x44,0xcf,0xd8} + * - b2 = {0x30,0x86,0xd2,0x21,0xa7,0xd4,0x6b,0xcd,0xe8,0x6c,0x90,0xe4,0x92,0x84,0xeb,0x15} + * + * The algorithm then computes c1 = round(b1 * k / n) and c2 = round(b2 * k / n), and gives + * k1 = k - (c1*a1 + c2*a2) and k2 = -(c1*b1 + c2*b2). Instead, we use modular arithmetic, and + * compute k1 as k - k2 * lambda, avoiding the need for constants a1 and a2. + * + * g1, g2 are precomputed constants used to replace division with a rounded multiplication + * when decomposing the scalar for an endomorphism-based point multiplication. + * + * The possibility of using precomputed estimates is mentioned in "Guide to Elliptic Curve + * Cryptography" (Hankerson, Menezes, Vanstone) in section 3.5. + * + * The derivation is described in the paper "Efficient Software Implementation of Public-Key + * Cryptography on Sensor Networks Using the MSP430X Microcontroller" (Gouvea, Oliveira, Lopez), + * Section 4.3 (here we use a somewhat higher-precision estimate): + * d = a1*b2 - b1*a2 + * g1 = round((2^272)*b2/d) + * g2 = round((2^272)*b1/d) + * + * (Note that 'd' is also equal to the curve order here because [a1,b1] and [a2,b2] are found + * as outputs of the Extended Euclidean Algorithm on inputs 'order' and 'lambda'). + * + * The function below splits a in r1 and r2, such that r1 + lambda * r2 == a (mod order). + */ + +static void secp256k1_scalar_split_lambda(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + secp256k1_scalar c1, c2; + static const secp256k1_scalar minus_lambda = SECP256K1_SCALAR_CONST( + 0xAC9C52B3UL, 0x3FA3CF1FUL, 0x5AD9E3FDUL, 0x77ED9BA4UL, + 0xA880B9FCUL, 0x8EC739C2UL, 0xE0CFC810UL, 0xB51283CFUL + ); + static const secp256k1_scalar minus_b1 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, + 0xE4437ED6UL, 0x010E8828UL, 0x6F547FA9UL, 0x0ABFE4C3UL + ); + static const secp256k1_scalar minus_b2 = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, + 0x8A280AC5UL, 0x0774346DUL, 0xD765CDA8UL, 0x3DB1562CUL + ); + static const secp256k1_scalar g1 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00003086UL, + 0xD221A7D4UL, 0x6BCDE86CUL, 0x90E49284UL, 0xEB153DABUL + ); + static const secp256k1_scalar g2 = SECP256K1_SCALAR_CONST( + 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0000E443UL, + 0x7ED6010EUL, 0x88286F54UL, 0x7FA90ABFUL, 0xE4C42212UL + ); + VERIFY_CHECK(r1 != a); + VERIFY_CHECK(r2 != a); + /* these _var calls are constant time since the shift amount is constant */ + secp256k1_scalar_mul_shift_var(&c1, a, &g1, 272); + secp256k1_scalar_mul_shift_var(&c2, a, &g2, 272); + secp256k1_scalar_mul(&c1, &c1, &minus_b1); + secp256k1_scalar_mul(&c2, &c2, &minus_b2); + secp256k1_scalar_add(r2, &c1, &c2); + secp256k1_scalar_mul(r1, r2, &minus_lambda); + secp256k1_scalar_add(r1, r1, a); +} +#endif +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h new file mode 100644 index 00000000..5574c44c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low.h @@ -0,0 +1,15 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_ +#define _SECP256K1_SCALAR_REPR_ + +#include + +/** A scalar modulo the group order of the secp256k1 curve. */ +typedef uint32_t secp256k1_scalar; + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h new file mode 100644 index 00000000..4f94441f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/scalar_low_impl.h @@ -0,0 +1,114 @@ +/********************************************************************** + * Copyright (c) 2015 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_SCALAR_REPR_IMPL_H_ +#define _SECP256K1_SCALAR_REPR_IMPL_H_ + +#include "scalar.h" + +#include + +SECP256K1_INLINE static int secp256k1_scalar_is_even(const secp256k1_scalar *a) { + return !(*a & 1); +} + +SECP256K1_INLINE static void secp256k1_scalar_clear(secp256k1_scalar *r) { *r = 0; } +SECP256K1_INLINE static void secp256k1_scalar_set_int(secp256k1_scalar *r, unsigned int v) { *r = v; } + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + if (offset < 32) + return ((*a >> offset) & ((((uint32_t)1) << count) - 1)); + else + return 0; +} + +SECP256K1_INLINE static unsigned int secp256k1_scalar_get_bits_var(const secp256k1_scalar *a, unsigned int offset, unsigned int count) { + return secp256k1_scalar_get_bits(a, offset, count); +} + +SECP256K1_INLINE static int secp256k1_scalar_check_overflow(const secp256k1_scalar *a) { return *a >= EXHAUSTIVE_TEST_ORDER; } + +static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + *r = (*a + *b) % EXHAUSTIVE_TEST_ORDER; + return *r < *b; +} + +static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) { + if (flag && bit < 32) + *r += (1 << bit); +#ifdef VERIFY + VERIFY_CHECK(secp256k1_scalar_check_overflow(r) == 0); +#endif +} + +static void secp256k1_scalar_set_b32(secp256k1_scalar *r, const unsigned char *b32, int *overflow) { + const int base = 0x100 % EXHAUSTIVE_TEST_ORDER; + int i; + *r = 0; + for (i = 0; i < 32; i++) { + *r = ((*r * base) + b32[i]) % EXHAUSTIVE_TEST_ORDER; + } + /* just deny overflow, it basically always happens */ + if (overflow) *overflow = 0; +} + +static void secp256k1_scalar_get_b32(unsigned char *bin, const secp256k1_scalar* a) { + memset(bin, 0, 32); + bin[28] = *a >> 24; bin[29] = *a >> 16; bin[30] = *a >> 8; bin[31] = *a; +} + +SECP256K1_INLINE static int secp256k1_scalar_is_zero(const secp256k1_scalar *a) { + return *a == 0; +} + +static void secp256k1_scalar_negate(secp256k1_scalar *r, const secp256k1_scalar *a) { + if (*a == 0) { + *r = 0; + } else { + *r = EXHAUSTIVE_TEST_ORDER - *a; + } +} + +SECP256K1_INLINE static int secp256k1_scalar_is_one(const secp256k1_scalar *a) { + return *a == 1; +} + +static int secp256k1_scalar_is_high(const secp256k1_scalar *a) { + return *a > EXHAUSTIVE_TEST_ORDER / 2; +} + +static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) { + if (flag) secp256k1_scalar_negate(r, r); + return flag ? -1 : 1; +} + +static void secp256k1_scalar_mul(secp256k1_scalar *r, const secp256k1_scalar *a, const secp256k1_scalar *b) { + *r = (*a * *b) % EXHAUSTIVE_TEST_ORDER; +} + +static int secp256k1_scalar_shr_int(secp256k1_scalar *r, int n) { + int ret; + VERIFY_CHECK(n > 0); + VERIFY_CHECK(n < 16); + ret = *r & ((1 << n) - 1); + *r >>= n; + return ret; +} + +static void secp256k1_scalar_sqr(secp256k1_scalar *r, const secp256k1_scalar *a) { + *r = (*a * *a) % EXHAUSTIVE_TEST_ORDER; +} + +static void secp256k1_scalar_split_128(secp256k1_scalar *r1, secp256k1_scalar *r2, const secp256k1_scalar *a) { + *r1 = *a; + *r2 = 0; +} + +SECP256K1_INLINE static int secp256k1_scalar_eq(const secp256k1_scalar *a, const secp256k1_scalar *b) { + return *a == *b; +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c new file mode 100755 index 00000000..fb8b882f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/secp256k1.c @@ -0,0 +1,561 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#include "include/secp256k1.h" + +#include "util.h" +#include "num_impl.h" +#include "field_impl.h" +#include "scalar_impl.h" +#include "group_impl.h" +#include "ecmult_impl.h" +#include "ecmult_const_impl.h" +#include "ecmult_gen_impl.h" +#include "ecdsa_impl.h" +#include "eckey_impl.h" +#include "hash_impl.h" + +#define ARG_CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + secp256k1_callback_call(&ctx->illegal_callback, #cond); \ + return 0; \ + } \ +} while(0) + +static void default_illegal_callback_fn(const char* str, void* data) { + (void)data; + fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str); + abort(); +} + +static const secp256k1_callback default_illegal_callback = { + default_illegal_callback_fn, + NULL +}; + +static void default_error_callback_fn(const char* str, void* data) { + (void)data; + fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str); + abort(); +} + +static const secp256k1_callback default_error_callback = { + default_error_callback_fn, + NULL +}; + + +struct secp256k1_context_struct { + secp256k1_ecmult_context ecmult_ctx; + secp256k1_ecmult_gen_context ecmult_gen_ctx; + secp256k1_callback illegal_callback; + secp256k1_callback error_callback; +}; + +secp256k1_context* secp256k1_context_create(unsigned int flags) { + secp256k1_context* ret = (secp256k1_context*)checked_malloc(&default_error_callback, sizeof(secp256k1_context)); + ret->illegal_callback = default_illegal_callback; + ret->error_callback = default_error_callback; + + if (EXPECT((flags & SECP256K1_FLAGS_TYPE_MASK) != SECP256K1_FLAGS_TYPE_CONTEXT, 0)) { + secp256k1_callback_call(&ret->illegal_callback, + "Invalid flags"); + free(ret); + return NULL; + } + + secp256k1_ecmult_context_init(&ret->ecmult_ctx); + secp256k1_ecmult_gen_context_init(&ret->ecmult_gen_ctx); + + if (flags & SECP256K1_FLAGS_BIT_CONTEXT_SIGN) { + secp256k1_ecmult_gen_context_build(&ret->ecmult_gen_ctx, &ret->error_callback); + } + if (flags & SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) { + secp256k1_ecmult_context_build(&ret->ecmult_ctx, &ret->error_callback); + } + + return ret; +} + +secp256k1_context* secp256k1_context_clone(const secp256k1_context* ctx) { + secp256k1_context* ret = (secp256k1_context*)checked_malloc(&ctx->error_callback, sizeof(secp256k1_context)); + ret->illegal_callback = ctx->illegal_callback; + ret->error_callback = ctx->error_callback; + secp256k1_ecmult_context_clone(&ret->ecmult_ctx, &ctx->ecmult_ctx, &ctx->error_callback); + secp256k1_ecmult_gen_context_clone(&ret->ecmult_gen_ctx, &ctx->ecmult_gen_ctx, &ctx->error_callback); + return ret; +} + +void secp256k1_context_destroy(secp256k1_context* ctx) { + if (ctx != NULL) { + secp256k1_ecmult_context_clear(&ctx->ecmult_ctx); + secp256k1_ecmult_gen_context_clear(&ctx->ecmult_gen_ctx); + + free(ctx); + } +} + +void secp256k1_context_set_illegal_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + if (fun == NULL) { + fun = default_illegal_callback_fn; + } + ctx->illegal_callback.fn = fun; + ctx->illegal_callback.data = data; +} + +void secp256k1_context_set_error_callback(secp256k1_context* ctx, void (*fun)(const char* message, void* data), const void* data) { + if (fun == NULL) { + fun = default_error_callback_fn; + } + ctx->error_callback.fn = fun; + ctx->error_callback.data = data; +} + +static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge, const secp256k1_pubkey* pubkey) { + if (sizeof(secp256k1_ge_storage) == 64) { + /* When the secp256k1_ge_storage type is exactly 64 byte, use its + * representation inside secp256k1_pubkey, as conversion is very fast. + * Note that secp256k1_pubkey_save must use the same representation. */ + secp256k1_ge_storage s; + memcpy(&s, &pubkey->data[0], 64); + secp256k1_ge_from_storage(ge, &s); + } else { + /* Otherwise, fall back to 32-byte big endian for X and Y. */ + secp256k1_fe x, y; + secp256k1_fe_set_b32(&x, pubkey->data); + secp256k1_fe_set_b32(&y, pubkey->data + 32); + secp256k1_ge_set_xy(ge, &x, &y); + } + ARG_CHECK(!secp256k1_fe_is_zero(&ge->x)); + return 1; +} + +static void secp256k1_pubkey_save(secp256k1_pubkey* pubkey, secp256k1_ge* ge) { + if (sizeof(secp256k1_ge_storage) == 64) { + secp256k1_ge_storage s; + secp256k1_ge_to_storage(&s, ge); + memcpy(&pubkey->data[0], &s, 64); + } else { + VERIFY_CHECK(!secp256k1_ge_is_infinity(ge)); + secp256k1_fe_normalize_var(&ge->x); + secp256k1_fe_normalize_var(&ge->y); + secp256k1_fe_get_b32(pubkey->data, &ge->x); + secp256k1_fe_get_b32(pubkey->data + 32, &ge->y); + } +} + +int secp256k1_ec_pubkey_parse(const secp256k1_context* ctx, secp256k1_pubkey* pubkey, const unsigned char *input, size_t inputlen) { + secp256k1_ge Q; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + memset(pubkey, 0, sizeof(*pubkey)); + ARG_CHECK(input != NULL); + if (!secp256k1_eckey_pubkey_parse(&Q, input, inputlen)) { + return 0; + } + secp256k1_pubkey_save(pubkey, &Q); + secp256k1_ge_clear(&Q); + return 1; +} + +int secp256k1_ec_pubkey_serialize(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_pubkey* pubkey, unsigned int flags) { + secp256k1_ge Q; + size_t len; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(outputlen != NULL); + ARG_CHECK(*outputlen >= ((flags & SECP256K1_FLAGS_BIT_COMPRESSION) ? 33 : 65)); + len = *outputlen; + *outputlen = 0; + ARG_CHECK(output != NULL); + memset(output, 0, len); + ARG_CHECK(pubkey != NULL); + ARG_CHECK((flags & SECP256K1_FLAGS_TYPE_MASK) == SECP256K1_FLAGS_TYPE_COMPRESSION); + if (secp256k1_pubkey_load(ctx, &Q, pubkey)) { + ret = secp256k1_eckey_pubkey_serialize(&Q, output, &len, flags & SECP256K1_FLAGS_BIT_COMPRESSION); + if (ret) { + *outputlen = len; + } + } + return ret; +} + +static void secp256k1_ecdsa_signature_load(const secp256k1_context* ctx, secp256k1_scalar* r, secp256k1_scalar* s, const secp256k1_ecdsa_signature* sig) { + (void)ctx; + if (sizeof(secp256k1_scalar) == 32) { + /* When the secp256k1_scalar type is exactly 32 byte, use its + * representation inside secp256k1_ecdsa_signature, as conversion is very fast. + * Note that secp256k1_ecdsa_signature_save must use the same representation. */ + memcpy(r, &sig->data[0], 32); + memcpy(s, &sig->data[32], 32); + } else { + secp256k1_scalar_set_b32(r, &sig->data[0], NULL); + secp256k1_scalar_set_b32(s, &sig->data[32], NULL); + } +} + +static void secp256k1_ecdsa_signature_save(secp256k1_ecdsa_signature* sig, const secp256k1_scalar* r, const secp256k1_scalar* s) { + if (sizeof(secp256k1_scalar) == 32) { + memcpy(&sig->data[0], r, 32); + memcpy(&sig->data[32], s, 32); + } else { + secp256k1_scalar_get_b32(&sig->data[0], r); + secp256k1_scalar_get_b32(&sig->data[32], s); + } +} + +int secp256k1_ecdsa_signature_parse_der(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input, size_t inputlen) { + secp256k1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(input != NULL); + + if (secp256k1_ecdsa_sig_parse(&r, &s, input, inputlen)) { + secp256k1_ecdsa_signature_save(sig, &r, &s); + return 1; + } else { + memset(sig, 0, sizeof(*sig)); + return 0; + } +} + +int secp256k1_ecdsa_signature_parse_compact(const secp256k1_context* ctx, secp256k1_ecdsa_signature* sig, const unsigned char *input64) { + secp256k1_scalar r, s; + int ret = 1; + int overflow = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(input64 != NULL); + + secp256k1_scalar_set_b32(&r, &input64[0], &overflow); + ret &= !overflow; + secp256k1_scalar_set_b32(&s, &input64[32], &overflow); + ret &= !overflow; + if (ret) { + secp256k1_ecdsa_signature_save(sig, &r, &s); + } else { + memset(sig, 0, sizeof(*sig)); + } + return ret; +} + +int secp256k1_ecdsa_signature_serialize_der(const secp256k1_context* ctx, unsigned char *output, size_t *outputlen, const secp256k1_ecdsa_signature* sig) { + secp256k1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output != NULL); + ARG_CHECK(outputlen != NULL); + ARG_CHECK(sig != NULL); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); + return secp256k1_ecdsa_sig_serialize(output, outputlen, &r, &s); +} + +int secp256k1_ecdsa_signature_serialize_compact(const secp256k1_context* ctx, unsigned char *output64, const secp256k1_ecdsa_signature* sig) { + secp256k1_scalar r, s; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(output64 != NULL); + ARG_CHECK(sig != NULL); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); + secp256k1_scalar_get_b32(&output64[0], &r); + secp256k1_scalar_get_b32(&output64[32], &s); + return 1; +} + +int secp256k1_ecdsa_signature_normalize(const secp256k1_context* ctx, secp256k1_ecdsa_signature *sigout, const secp256k1_ecdsa_signature *sigin) { + secp256k1_scalar r, s; + int ret = 0; + + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(sigin != NULL); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, sigin); + ret = secp256k1_scalar_is_high(&s); + if (sigout != NULL) { + if (ret) { + secp256k1_scalar_negate(&s, &s); + } + secp256k1_ecdsa_signature_save(sigout, &r, &s); + } + + return ret; +} + +int secp256k1_ecdsa_verify(const secp256k1_context* ctx, const secp256k1_ecdsa_signature *sig, const unsigned char *msg32, const secp256k1_pubkey *pubkey) { + secp256k1_ge q; + secp256k1_scalar r, s; + secp256k1_scalar m; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(sig != NULL); + ARG_CHECK(pubkey != NULL); + + secp256k1_scalar_set_b32(&m, msg32, NULL); + secp256k1_ecdsa_signature_load(ctx, &r, &s, sig); + return (!secp256k1_scalar_is_high(&s) && + secp256k1_pubkey_load(ctx, &q, pubkey) && + secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &r, &s, &q, &m)); +} + +static int nonce_function_rfc6979(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + unsigned char keydata[112]; + int keylen = 64; + secp256k1_rfc6979_hmac_sha256_t rng; + unsigned int i; + /* We feed a byte array to the PRNG as input, consisting of: + * - the private key (32 bytes) and message (32 bytes), see RFC 6979 3.2d. + * - optionally 32 extra bytes of data, see RFC 6979 3.6 Additional Data. + * - optionally 16 extra bytes with the algorithm name. + * Because the arguments have distinct fixed lengths it is not possible for + * different argument mixtures to emulate each other and result in the same + * nonces. + */ + memcpy(keydata, key32, 32); + memcpy(keydata + 32, msg32, 32); + if (data != NULL) { + memcpy(keydata + 64, data, 32); + keylen = 96; + } + if (algo16 != NULL) { + memcpy(keydata + keylen, algo16, 16); + keylen += 16; + } + secp256k1_rfc6979_hmac_sha256_initialize(&rng, keydata, keylen); + memset(keydata, 0, sizeof(keydata)); + for (i = 0; i <= counter; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + return 1; +} + +const secp256k1_nonce_function secp256k1_nonce_function_rfc6979 = nonce_function_rfc6979; +const secp256k1_nonce_function secp256k1_nonce_function_default = nonce_function_rfc6979; + +int secp256k1_ecdsa_sign(const secp256k1_context* ctx, secp256k1_ecdsa_signature *signature, const unsigned char *msg32, const unsigned char *seckey, secp256k1_nonce_function noncefp, const void* noncedata) { + secp256k1_scalar r, s; + secp256k1_scalar sec, non, msg; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(msg32 != NULL); + ARG_CHECK(signature != NULL); + ARG_CHECK(seckey != NULL); + if (noncefp == NULL) { + noncefp = secp256k1_nonce_function_default; + } + + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + /* Fail if the secret key is invalid. */ + if (!overflow && !secp256k1_scalar_is_zero(&sec)) { + unsigned char nonce32[32]; + unsigned int count = 0; + secp256k1_scalar_set_b32(&msg, msg32, NULL); + while (1) { + ret = noncefp(nonce32, msg32, seckey, NULL, (void*)noncedata, count); + if (!ret) { + break; + } + secp256k1_scalar_set_b32(&non, nonce32, &overflow); + if (!overflow && !secp256k1_scalar_is_zero(&non)) { + if (secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, &r, &s, &sec, &msg, &non, NULL)) { + break; + } + } + count++; + } + memset(nonce32, 0, 32); + secp256k1_scalar_clear(&msg); + secp256k1_scalar_clear(&non); + secp256k1_scalar_clear(&sec); + } + if (ret) { + secp256k1_ecdsa_signature_save(signature, &r, &s); + } else { + memset(signature, 0, sizeof(*signature)); + } + return ret; +} + +int secp256k1_ec_seckey_verify(const secp256k1_context* ctx, const unsigned char *seckey) { + secp256k1_scalar sec; + int ret; + int overflow; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + ret = !overflow && !secp256k1_scalar_is_zero(&sec); + secp256k1_scalar_clear(&sec); + return ret; +} + +int secp256k1_ec_pubkey_create(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *seckey) { + secp256k1_gej pj; + secp256k1_ge p; + secp256k1_scalar sec; + int overflow; + int ret = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(pubkey != NULL); + memset(pubkey, 0, sizeof(*pubkey)); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + ARG_CHECK(seckey != NULL); + + secp256k1_scalar_set_b32(&sec, seckey, &overflow); + ret = (!overflow) & (!secp256k1_scalar_is_zero(&sec)); + if (ret) { + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pj, &sec); + secp256k1_ge_set_gej(&p, &pj); + secp256k1_pubkey_save(pubkey, &p); + } + secp256k1_scalar_clear(&sec); + return ret; +} + +int secp256k1_ec_privkey_tweak_add(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { + secp256k1_scalar term; + secp256k1_scalar sec; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + ARG_CHECK(tweak != NULL); + + secp256k1_scalar_set_b32(&term, tweak, &overflow); + secp256k1_scalar_set_b32(&sec, seckey, NULL); + + ret = !overflow && secp256k1_eckey_privkey_tweak_add(&sec, &term); + memset(seckey, 0, 32); + if (ret) { + secp256k1_scalar_get_b32(seckey, &sec); + } + + secp256k1_scalar_clear(&sec); + secp256k1_scalar_clear(&term); + return ret; +} + +int secp256k1_ec_pubkey_tweak_add(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { + secp256k1_ge p; + secp256k1_scalar term; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(tweak != NULL); + + secp256k1_scalar_set_b32(&term, tweak, &overflow); + ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + if (secp256k1_eckey_pubkey_tweak_add(&ctx->ecmult_ctx, &p, &term)) { + secp256k1_pubkey_save(pubkey, &p); + } else { + ret = 0; + } + } + + return ret; +} + +int secp256k1_ec_privkey_tweak_mul(const secp256k1_context* ctx, unsigned char *seckey, const unsigned char *tweak) { + secp256k1_scalar factor; + secp256k1_scalar sec; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(seckey != NULL); + ARG_CHECK(tweak != NULL); + + secp256k1_scalar_set_b32(&factor, tweak, &overflow); + secp256k1_scalar_set_b32(&sec, seckey, NULL); + ret = !overflow && secp256k1_eckey_privkey_tweak_mul(&sec, &factor); + memset(seckey, 0, 32); + if (ret) { + secp256k1_scalar_get_b32(seckey, &sec); + } + + secp256k1_scalar_clear(&sec); + secp256k1_scalar_clear(&factor); + return ret; +} + +int secp256k1_ec_pubkey_tweak_mul(const secp256k1_context* ctx, secp256k1_pubkey *pubkey, const unsigned char *tweak) { + secp256k1_ge p; + secp256k1_scalar factor; + int ret = 0; + int overflow = 0; + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_context_is_built(&ctx->ecmult_ctx)); + ARG_CHECK(pubkey != NULL); + ARG_CHECK(tweak != NULL); + + secp256k1_scalar_set_b32(&factor, tweak, &overflow); + ret = !overflow && secp256k1_pubkey_load(ctx, &p, pubkey); + memset(pubkey, 0, sizeof(*pubkey)); + if (ret) { + if (secp256k1_eckey_pubkey_tweak_mul(&ctx->ecmult_ctx, &p, &factor)) { + secp256k1_pubkey_save(pubkey, &p); + } else { + ret = 0; + } + } + + return ret; +} + +int secp256k1_context_randomize(secp256k1_context* ctx, const unsigned char *seed32) { + VERIFY_CHECK(ctx != NULL); + ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx)); + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + return 1; +} + +int secp256k1_ec_pubkey_combine(const secp256k1_context* ctx, secp256k1_pubkey *pubnonce, const secp256k1_pubkey * const *pubnonces, size_t n) { + size_t i; + secp256k1_gej Qj; + secp256k1_ge Q; + + ARG_CHECK(pubnonce != NULL); + memset(pubnonce, 0, sizeof(*pubnonce)); + ARG_CHECK(n >= 1); + ARG_CHECK(pubnonces != NULL); + + secp256k1_gej_set_infinity(&Qj); + + for (i = 0; i < n; i++) { + secp256k1_pubkey_load(ctx, &Q, pubnonces[i]); + secp256k1_gej_add_ge(&Qj, &Qj, &Q); + } + if (secp256k1_gej_is_infinity(&Qj)) { + return 0; + } + secp256k1_ge_set_gej(&Q, &Qj); + secp256k1_pubkey_save(pubnonce, &Q); + return 1; +} + +#ifdef ENABLE_MODULE_ECDH +# include "modules/ecdh/main_impl.h" +#endif + +#ifdef ENABLE_MODULE_SCHNORR +# include "modules/schnorr/main_impl.h" +#endif + +#ifdef ENABLE_MODULE_RECOVERY +# include "modules/recovery/main_impl.h" +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h new file mode 100644 index 00000000..f8efa93c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand.h @@ -0,0 +1,38 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_TESTRAND_H_ +#define _SECP256K1_TESTRAND_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +/* A non-cryptographic RNG used only for test infrastructure. */ + +/** Seed the pseudorandom number generator for testing. */ +SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16); + +/** Generate a pseudorandom number in the range [0..2**32-1]. */ +static uint32_t secp256k1_rand32(void); + +/** Generate a pseudorandom number in the range [0..2**bits-1]. Bits must be 1 or + * more. */ +static uint32_t secp256k1_rand_bits(int bits); + +/** Generate a pseudorandom number in the range [0..range-1]. */ +static uint32_t secp256k1_rand_int(uint32_t range); + +/** Generate a pseudorandom 32-byte array. */ +static void secp256k1_rand256(unsigned char *b32); + +/** Generate a pseudorandom 32-byte array with long sequences of zero and one bits. */ +static void secp256k1_rand256_test(unsigned char *b32); + +/** Generate pseudorandom bytes with long sequences of zero and one bits. */ +static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len); + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h new file mode 100644 index 00000000..15c7b9f1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/testrand_impl.h @@ -0,0 +1,110 @@ +/********************************************************************** + * Copyright (c) 2013-2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_TESTRAND_IMPL_H_ +#define _SECP256K1_TESTRAND_IMPL_H_ + +#include +#include + +#include "testrand.h" +#include "hash.h" + +static secp256k1_rfc6979_hmac_sha256_t secp256k1_test_rng; +static uint32_t secp256k1_test_rng_precomputed[8]; +static int secp256k1_test_rng_precomputed_used = 8; +static uint64_t secp256k1_test_rng_integer; +static int secp256k1_test_rng_integer_bits_left = 0; + +SECP256K1_INLINE static void secp256k1_rand_seed(const unsigned char *seed16) { + secp256k1_rfc6979_hmac_sha256_initialize(&secp256k1_test_rng, seed16, 16); +} + +SECP256K1_INLINE static uint32_t secp256k1_rand32(void) { + if (secp256k1_test_rng_precomputed_used == 8) { + secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, (unsigned char*)(&secp256k1_test_rng_precomputed[0]), sizeof(secp256k1_test_rng_precomputed)); + secp256k1_test_rng_precomputed_used = 0; + } + return secp256k1_test_rng_precomputed[secp256k1_test_rng_precomputed_used++]; +} + +static uint32_t secp256k1_rand_bits(int bits) { + uint32_t ret; + if (secp256k1_test_rng_integer_bits_left < bits) { + secp256k1_test_rng_integer |= (((uint64_t)secp256k1_rand32()) << secp256k1_test_rng_integer_bits_left); + secp256k1_test_rng_integer_bits_left += 32; + } + ret = secp256k1_test_rng_integer; + secp256k1_test_rng_integer >>= bits; + secp256k1_test_rng_integer_bits_left -= bits; + ret &= ((~((uint32_t)0)) >> (32 - bits)); + return ret; +} + +static uint32_t secp256k1_rand_int(uint32_t range) { + /* We want a uniform integer between 0 and range-1, inclusive. + * B is the smallest number such that range <= 2**B. + * two mechanisms implemented here: + * - generate B bits numbers until one below range is found, and return it + * - find the largest multiple M of range that is <= 2**(B+A), generate B+A + * bits numbers until one below M is found, and return it modulo range + * The second mechanism consumes A more bits of entropy in every iteration, + * but may need fewer iterations due to M being closer to 2**(B+A) then + * range is to 2**B. The array below (indexed by B) contains a 0 when the + * first mechanism is to be used, and the number A otherwise. + */ + static const int addbits[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0}; + uint32_t trange, mult; + int bits = 0; + if (range <= 1) { + return 0; + } + trange = range - 1; + while (trange > 0) { + trange >>= 1; + bits++; + } + if (addbits[bits]) { + bits = bits + addbits[bits]; + mult = ((~((uint32_t)0)) >> (32 - bits)) / range; + trange = range * mult; + } else { + trange = range; + mult = 1; + } + while(1) { + uint32_t x = secp256k1_rand_bits(bits); + if (x < trange) { + return (mult == 1) ? x : (x % range); + } + } +} + +static void secp256k1_rand256(unsigned char *b32) { + secp256k1_rfc6979_hmac_sha256_generate(&secp256k1_test_rng, b32, 32); +} + +static void secp256k1_rand_bytes_test(unsigned char *bytes, size_t len) { + size_t bits = 0; + memset(bytes, 0, len); + while (bits < len * 8) { + int now; + uint32_t val; + now = 1 + (secp256k1_rand_bits(6) * secp256k1_rand_bits(5) + 16) / 31; + val = secp256k1_rand_bits(1); + while (now > 0 && bits < len * 8) { + bytes[bits / 8] |= val << (bits % 8); + now--; + bits++; + } + } +} + +static void secp256k1_rand256_test(unsigned char *b32) { + secp256k1_rand_bytes_test(b32, 32); +} + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c new file mode 100644 index 00000000..9ae7d302 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests.c @@ -0,0 +1,4525 @@ +/********************************************************************** + * Copyright (c) 2013, 2014, 2015 Pieter Wuille, Gregory Maxwell * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include +#include + +#include + +#include "secp256k1.c" +#include "include/secp256k1.h" +#include "testrand_impl.h" + +#ifdef ENABLE_OPENSSL_TESTS +#include "openssl/bn.h" +#include "openssl/ec.h" +#include "openssl/ecdsa.h" +#include "openssl/obj_mac.h" +#endif + +#include "contrib/lax_der_parsing.c" +#include "contrib/lax_der_privatekey_parsing.c" + +#if !defined(VG_CHECK) +# if defined(VALGRIND) +# include +# define VG_UNDEF(x,y) VALGRIND_MAKE_MEM_UNDEFINED((x),(y)) +# define VG_CHECK(x,y) VALGRIND_CHECK_MEM_IS_DEFINED((x),(y)) +# else +# define VG_UNDEF(x,y) +# define VG_CHECK(x,y) +# endif +#endif + +static int count = 64; +static secp256k1_context *ctx = NULL; + +static void counting_illegal_callback_fn(const char* str, void* data) { + /* Dummy callback function that just counts. */ + int32_t *p; + (void)str; + p = data; + (*p)++; +} + +static void uncounting_illegal_callback_fn(const char* str, void* data) { + /* Dummy callback function that just counts (backwards). */ + int32_t *p; + (void)str; + p = data; + (*p)--; +} + +void random_field_element_test(secp256k1_fe *fe) { + do { + unsigned char b32[32]; + secp256k1_rand256_test(b32); + if (secp256k1_fe_set_b32(fe, b32)) { + break; + } + } while(1); +} + +void random_field_element_magnitude(secp256k1_fe *fe) { + secp256k1_fe zero; + int n = secp256k1_rand_int(9); + secp256k1_fe_normalize(fe); + if (n == 0) { + return; + } + secp256k1_fe_clear(&zero); + secp256k1_fe_negate(&zero, &zero, 0); + secp256k1_fe_mul_int(&zero, n - 1); + secp256k1_fe_add(fe, &zero); + VERIFY_CHECK(fe->magnitude == n); +} + +void random_group_element_test(secp256k1_ge *ge) { + secp256k1_fe fe; + do { + random_field_element_test(&fe); + if (secp256k1_ge_set_xo_var(ge, &fe, secp256k1_rand_bits(1))) { + secp256k1_fe_normalize(&ge->y); + break; + } + } while(1); +} + +void random_group_element_jacobian_test(secp256k1_gej *gej, const secp256k1_ge *ge) { + secp256k1_fe z2, z3; + do { + random_field_element_test(&gej->z); + if (!secp256k1_fe_is_zero(&gej->z)) { + break; + } + } while(1); + secp256k1_fe_sqr(&z2, &gej->z); + secp256k1_fe_mul(&z3, &z2, &gej->z); + secp256k1_fe_mul(&gej->x, &ge->x, &z2); + secp256k1_fe_mul(&gej->y, &ge->y, &z3); + gej->infinity = ge->infinity; +} + +void random_scalar_order_test(secp256k1_scalar *num) { + do { + unsigned char b32[32]; + int overflow = 0; + secp256k1_rand256_test(b32); + secp256k1_scalar_set_b32(num, b32, &overflow); + if (overflow || secp256k1_scalar_is_zero(num)) { + continue; + } + break; + } while(1); +} + +void random_scalar_order(secp256k1_scalar *num) { + do { + unsigned char b32[32]; + int overflow = 0; + secp256k1_rand256(b32); + secp256k1_scalar_set_b32(num, b32, &overflow); + if (overflow || secp256k1_scalar_is_zero(num)) { + continue; + } + break; + } while(1); +} + +void run_context_tests(void) { + secp256k1_pubkey pubkey; + secp256k1_ecdsa_signature sig; + unsigned char ctmp[32]; + int32_t ecount; + int32_t ecount2; + secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + secp256k1_context *sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + secp256k1_context *vrfy = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + secp256k1_context *both = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + secp256k1_gej pubj; + secp256k1_ge pub; + secp256k1_scalar msg, key, nonce; + secp256k1_scalar sigr, sigs; + + ecount = 0; + ecount2 = 10; + secp256k1_context_set_illegal_callback(vrfy, counting_illegal_callback_fn, &ecount); + secp256k1_context_set_illegal_callback(sign, counting_illegal_callback_fn, &ecount2); + secp256k1_context_set_error_callback(sign, counting_illegal_callback_fn, NULL); + CHECK(vrfy->error_callback.fn != sign->error_callback.fn); + + /*** clone and destroy all of them to make sure cloning was complete ***/ + { + secp256k1_context *ctx_tmp; + + ctx_tmp = none; none = secp256k1_context_clone(none); secp256k1_context_destroy(ctx_tmp); + ctx_tmp = sign; sign = secp256k1_context_clone(sign); secp256k1_context_destroy(ctx_tmp); + ctx_tmp = vrfy; vrfy = secp256k1_context_clone(vrfy); secp256k1_context_destroy(ctx_tmp); + ctx_tmp = both; both = secp256k1_context_clone(both); secp256k1_context_destroy(ctx_tmp); + } + + /* Verify that the error callback makes it across the clone. */ + CHECK(vrfy->error_callback.fn != sign->error_callback.fn); + /* And that it resets back to default. */ + secp256k1_context_set_error_callback(sign, NULL, NULL); + CHECK(vrfy->error_callback.fn == sign->error_callback.fn); + + /*** attempt to use them ***/ + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_ecmult_gen(&both->ecmult_gen_ctx, &pubj, &key); + secp256k1_ge_set_gej(&pub, &pubj); + + /* Verify context-type checking illegal-argument errors. */ + memset(ctmp, 1, 32); + CHECK(secp256k1_ec_pubkey_create(vrfy, &pubkey, ctmp) == 0); + CHECK(ecount == 1); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(sign, &pubkey, ctmp) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ecdsa_sign(vrfy, &sig, ctmp, ctmp, NULL, NULL) == 0); + CHECK(ecount == 2); + VG_UNDEF(&sig, sizeof(sig)); + CHECK(secp256k1_ecdsa_sign(sign, &sig, ctmp, ctmp, NULL, NULL) == 1); + VG_CHECK(&sig, sizeof(sig)); + CHECK(ecount2 == 10); + CHECK(secp256k1_ecdsa_verify(sign, &sig, ctmp, &pubkey) == 0); + CHECK(ecount2 == 11); + CHECK(secp256k1_ecdsa_verify(vrfy, &sig, ctmp, &pubkey) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ec_pubkey_tweak_add(sign, &pubkey, ctmp) == 0); + CHECK(ecount2 == 12); + CHECK(secp256k1_ec_pubkey_tweak_add(vrfy, &pubkey, ctmp) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_ec_pubkey_tweak_mul(sign, &pubkey, ctmp) == 0); + CHECK(ecount2 == 13); + CHECK(secp256k1_ec_pubkey_tweak_mul(vrfy, &pubkey, ctmp) == 1); + CHECK(ecount == 2); + CHECK(secp256k1_context_randomize(vrfy, ctmp) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_context_randomize(sign, NULL) == 1); + CHECK(ecount2 == 13); + secp256k1_context_set_illegal_callback(vrfy, NULL, NULL); + secp256k1_context_set_illegal_callback(sign, NULL, NULL); + + /* This shouldn't leak memory, due to already-set tests. */ + secp256k1_ecmult_gen_context_build(&sign->ecmult_gen_ctx, NULL); + secp256k1_ecmult_context_build(&vrfy->ecmult_ctx, NULL); + + /* obtain a working nonce */ + do { + random_scalar_order_test(&nonce); + } while(!secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + + /* try signing */ + CHECK(secp256k1_ecdsa_sig_sign(&sign->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + CHECK(secp256k1_ecdsa_sig_sign(&both->ecmult_gen_ctx, &sigr, &sigs, &key, &msg, &nonce, NULL)); + + /* try verifying */ + CHECK(secp256k1_ecdsa_sig_verify(&vrfy->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + CHECK(secp256k1_ecdsa_sig_verify(&both->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + + /* cleanup */ + secp256k1_context_destroy(none); + secp256k1_context_destroy(sign); + secp256k1_context_destroy(vrfy); + secp256k1_context_destroy(both); + /* Defined as no-op. */ + secp256k1_context_destroy(NULL); +} + +/***** HASH TESTS *****/ + +void run_sha256_tests(void) { + static const char *inputs[8] = { + "", "abc", "message digest", "secure hash algorithm", "SHA256 is considered to be safe", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "For this sample, this 63-byte string will be used as input data", + "This is exactly 64 bytes long, not counting the terminating byte" + }; + static const unsigned char outputs[8][32] = { + {0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}, + {0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad}, + {0xf7, 0x84, 0x6f, 0x55, 0xcf, 0x23, 0xe1, 0x4e, 0xeb, 0xea, 0xb5, 0xb4, 0xe1, 0x55, 0x0c, 0xad, 0x5b, 0x50, 0x9e, 0x33, 0x48, 0xfb, 0xc4, 0xef, 0xa3, 0xa1, 0x41, 0x3d, 0x39, 0x3c, 0xb6, 0x50}, + {0xf3, 0x0c, 0xeb, 0x2b, 0xb2, 0x82, 0x9e, 0x79, 0xe4, 0xca, 0x97, 0x53, 0xd3, 0x5a, 0x8e, 0xcc, 0x00, 0x26, 0x2d, 0x16, 0x4c, 0xc0, 0x77, 0x08, 0x02, 0x95, 0x38, 0x1c, 0xbd, 0x64, 0x3f, 0x0d}, + {0x68, 0x19, 0xd9, 0x15, 0xc7, 0x3f, 0x4d, 0x1e, 0x77, 0xe4, 0xe1, 0xb5, 0x2d, 0x1f, 0xa0, 0xf9, 0xcf, 0x9b, 0xea, 0xea, 0xd3, 0x93, 0x9f, 0x15, 0x87, 0x4b, 0xd9, 0x88, 0xe2, 0xa2, 0x36, 0x30}, + {0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1}, + {0xf0, 0x8a, 0x78, 0xcb, 0xba, 0xee, 0x08, 0x2b, 0x05, 0x2a, 0xe0, 0x70, 0x8f, 0x32, 0xfa, 0x1e, 0x50, 0xc5, 0xc4, 0x21, 0xaa, 0x77, 0x2b, 0xa5, 0xdb, 0xb4, 0x06, 0xa2, 0xea, 0x6b, 0xe3, 0x42}, + {0xab, 0x64, 0xef, 0xf7, 0xe8, 0x8e, 0x2e, 0x46, 0x16, 0x5e, 0x29, 0xf2, 0xbc, 0xe4, 0x18, 0x26, 0xbd, 0x4c, 0x7b, 0x35, 0x52, 0xf6, 0xb3, 0x82, 0xa9, 0xe7, 0xd3, 0xaf, 0x47, 0xc2, 0x45, 0xf8} + }; + int i; + for (i = 0; i < 8; i++) { + unsigned char out[32]; + secp256k1_sha256_t hasher; + secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + secp256k1_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + if (strlen(inputs[i]) > 0) { + int split = secp256k1_rand_int(strlen(inputs[i])); + secp256k1_sha256_initialize(&hasher); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + secp256k1_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + secp256k1_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + } + } +} + +void run_hmac_sha256_tests(void) { + static const char *keys[6] = { + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "\x4a\x65\x66\x65", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + }; + static const char *inputs[6] = { + "\x48\x69\x20\x54\x68\x65\x72\x65", + "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69\x72\x73\x74", + "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e" + }; + static const unsigned char outputs[6][32] = { + {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7}, + {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43}, + {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe}, + {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b}, + {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54}, + {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} + }; + int i; + for (i = 0; i < 6; i++) { + secp256k1_hmac_sha256_t hasher; + unsigned char out[32]; + secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), strlen(inputs[i])); + secp256k1_hmac_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + if (strlen(inputs[i]) > 0) { + int split = secp256k1_rand_int(strlen(inputs[i])); + secp256k1_hmac_sha256_initialize(&hasher, (const unsigned char*)(keys[i]), strlen(keys[i])); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i]), split); + secp256k1_hmac_sha256_write(&hasher, (const unsigned char*)(inputs[i] + split), strlen(inputs[i]) - split); + secp256k1_hmac_sha256_finalize(&hasher, out); + CHECK(memcmp(out, outputs[i], 32) == 0); + } + } +} + +void run_rfc6979_hmac_sha256_tests(void) { + static const unsigned char key1[65] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x00, 0x4b, 0xf5, 0x12, 0x2f, 0x34, 0x45, 0x54, 0xc5, 0x3b, 0xde, 0x2e, 0xbb, 0x8c, 0xd2, 0xb7, 0xe3, 0xd1, 0x60, 0x0a, 0xd6, 0x31, 0xc3, 0x85, 0xa5, 0xd7, 0xcc, 0xe2, 0x3c, 0x77, 0x85, 0x45, 0x9a, 0}; + static const unsigned char out1[3][32] = { + {0x4f, 0xe2, 0x95, 0x25, 0xb2, 0x08, 0x68, 0x09, 0x15, 0x9a, 0xcd, 0xf0, 0x50, 0x6e, 0xfb, 0x86, 0xb0, 0xec, 0x93, 0x2c, 0x7b, 0xa4, 0x42, 0x56, 0xab, 0x32, 0x1e, 0x42, 0x1e, 0x67, 0xe9, 0xfb}, + {0x2b, 0xf0, 0xff, 0xf1, 0xd3, 0xc3, 0x78, 0xa2, 0x2d, 0xc5, 0xde, 0x1d, 0x85, 0x65, 0x22, 0x32, 0x5c, 0x65, 0xb5, 0x04, 0x49, 0x1a, 0x0c, 0xbd, 0x01, 0xcb, 0x8f, 0x3a, 0xa6, 0x7f, 0xfd, 0x4a}, + {0xf5, 0x28, 0xb4, 0x10, 0xcb, 0x54, 0x1f, 0x77, 0x00, 0x0d, 0x7a, 0xfb, 0x6c, 0x5b, 0x53, 0xc5, 0xc4, 0x71, 0xea, 0xb4, 0x3e, 0x46, 0x6d, 0x9a, 0xc5, 0x19, 0x0c, 0x39, 0xc8, 0x2f, 0xd8, 0x2e} + }; + + static const unsigned char key2[64] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; + static const unsigned char out2[3][32] = { + {0x9c, 0x23, 0x6c, 0x16, 0x5b, 0x82, 0xae, 0x0c, 0xd5, 0x90, 0x65, 0x9e, 0x10, 0x0b, 0x6b, 0xab, 0x30, 0x36, 0xe7, 0xba, 0x8b, 0x06, 0x74, 0x9b, 0xaf, 0x69, 0x81, 0xe1, 0x6f, 0x1a, 0x2b, 0x95}, + {0xdf, 0x47, 0x10, 0x61, 0x62, 0x5b, 0xc0, 0xea, 0x14, 0xb6, 0x82, 0xfe, 0xee, 0x2c, 0x9c, 0x02, 0xf2, 0x35, 0xda, 0x04, 0x20, 0x4c, 0x1d, 0x62, 0xa1, 0x53, 0x6c, 0x6e, 0x17, 0xae, 0xd7, 0xa9}, + {0x75, 0x97, 0x88, 0x7c, 0xbd, 0x76, 0x32, 0x1f, 0x32, 0xe3, 0x04, 0x40, 0x67, 0x9a, 0x22, 0xcf, 0x7f, 0x8d, 0x9d, 0x2e, 0xac, 0x39, 0x0e, 0x58, 0x1f, 0xea, 0x09, 0x1c, 0xe2, 0x02, 0xba, 0x94} + }; + + secp256k1_rfc6979_hmac_sha256_t rng; + unsigned char out[32]; + int i; + + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 64); + for (i = 0; i < 3; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(memcmp(out, out1[i], 32) == 0); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key1, 65); + for (i = 0; i < 3; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(memcmp(out, out1[i], 32) != 0); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); + + secp256k1_rfc6979_hmac_sha256_initialize(&rng, key2, 64); + for (i = 0; i < 3; i++) { + secp256k1_rfc6979_hmac_sha256_generate(&rng, out, 32); + CHECK(memcmp(out, out2[i], 32) == 0); + } + secp256k1_rfc6979_hmac_sha256_finalize(&rng); +} + +/***** RANDOM TESTS *****/ + +void test_rand_bits(int rand32, int bits) { + /* (1-1/2^B)^rounds[B] < 1/10^9, so rounds is the number of iterations to + * get a false negative chance below once in a billion */ + static const unsigned int rounds[7] = {1, 30, 73, 156, 322, 653, 1316}; + /* We try multiplying the results with various odd numbers, which shouldn't + * influence the uniform distribution modulo a power of 2. */ + static const uint32_t mults[6] = {1, 3, 21, 289, 0x9999, 0x80402011}; + /* We only select up to 6 bits from the output to analyse */ + unsigned int usebits = bits > 6 ? 6 : bits; + unsigned int maxshift = bits - usebits; + /* For each of the maxshift+1 usebits-bit sequences inside a bits-bit + number, track all observed outcomes, one per bit in a uint64_t. */ + uint64_t x[6][27] = {{0}}; + unsigned int i, shift, m; + /* Multiply the output of all rand calls with the odd number m, which + should not change the uniformity of its distribution. */ + for (i = 0; i < rounds[usebits]; i++) { + uint32_t r = (rand32 ? secp256k1_rand32() : secp256k1_rand_bits(bits)); + CHECK((((uint64_t)r) >> bits) == 0); + for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { + uint32_t rm = r * mults[m]; + for (shift = 0; shift <= maxshift; shift++) { + x[m][shift] |= (((uint64_t)1) << ((rm >> shift) & ((1 << usebits) - 1))); + } + } + } + for (m = 0; m < sizeof(mults) / sizeof(mults[0]); m++) { + for (shift = 0; shift <= maxshift; shift++) { + /* Test that the lower usebits bits of x[shift] are 1 */ + CHECK(((~x[m][shift]) << (64 - (1 << usebits))) == 0); + } + } +} + +/* Subrange must be a whole divisor of range, and at most 64 */ +void test_rand_int(uint32_t range, uint32_t subrange) { + /* (1-1/subrange)^rounds < 1/10^9 */ + int rounds = (subrange * 2073) / 100; + int i; + uint64_t x = 0; + CHECK((range % subrange) == 0); + for (i = 0; i < rounds; i++) { + uint32_t r = secp256k1_rand_int(range); + CHECK(r < range); + r = r % subrange; + x |= (((uint64_t)1) << r); + } + /* Test that the lower subrange bits of x are 1. */ + CHECK(((~x) << (64 - subrange)) == 0); +} + +void run_rand_bits(void) { + size_t b; + test_rand_bits(1, 32); + for (b = 1; b <= 32; b++) { + test_rand_bits(0, b); + } +} + +void run_rand_int(void) { + static const uint32_t ms[] = {1, 3, 17, 1000, 13771, 999999, 33554432}; + static const uint32_t ss[] = {1, 3, 6, 9, 13, 31, 64}; + unsigned int m, s; + for (m = 0; m < sizeof(ms) / sizeof(ms[0]); m++) { + for (s = 0; s < sizeof(ss) / sizeof(ss[0]); s++) { + test_rand_int(ms[m] * ss[s], ss[s]); + } + } +} + +/***** NUM TESTS *****/ + +#ifndef USE_NUM_NONE +void random_num_negate(secp256k1_num *num) { + if (secp256k1_rand_bits(1)) { + secp256k1_num_negate(num); + } +} + +void random_num_order_test(secp256k1_num *num) { + secp256k1_scalar sc; + random_scalar_order_test(&sc); + secp256k1_scalar_get_num(num, &sc); +} + +void random_num_order(secp256k1_num *num) { + secp256k1_scalar sc; + random_scalar_order(&sc); + secp256k1_scalar_get_num(num, &sc); +} + +void test_num_negate(void) { + secp256k1_num n1; + secp256k1_num n2; + random_num_order_test(&n1); /* n1 = R */ + random_num_negate(&n1); + secp256k1_num_copy(&n2, &n1); /* n2 = R */ + secp256k1_num_sub(&n1, &n2, &n1); /* n1 = n2-n1 = 0 */ + CHECK(secp256k1_num_is_zero(&n1)); + secp256k1_num_copy(&n1, &n2); /* n1 = R */ + secp256k1_num_negate(&n1); /* n1 = -R */ + CHECK(!secp256k1_num_is_zero(&n1)); + secp256k1_num_add(&n1, &n2, &n1); /* n1 = n2+n1 = 0 */ + CHECK(secp256k1_num_is_zero(&n1)); + secp256k1_num_copy(&n1, &n2); /* n1 = R */ + secp256k1_num_negate(&n1); /* n1 = -R */ + CHECK(secp256k1_num_is_neg(&n1) != secp256k1_num_is_neg(&n2)); + secp256k1_num_negate(&n1); /* n1 = R */ + CHECK(secp256k1_num_eq(&n1, &n2)); +} + +void test_num_add_sub(void) { + int i; + secp256k1_scalar s; + secp256k1_num n1; + secp256k1_num n2; + secp256k1_num n1p2, n2p1, n1m2, n2m1; + random_num_order_test(&n1); /* n1 = R1 */ + if (secp256k1_rand_bits(1)) { + random_num_negate(&n1); + } + random_num_order_test(&n2); /* n2 = R2 */ + if (secp256k1_rand_bits(1)) { + random_num_negate(&n2); + } + secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = R1 + R2 */ + secp256k1_num_add(&n2p1, &n2, &n1); /* n2p1 = R2 + R1 */ + secp256k1_num_sub(&n1m2, &n1, &n2); /* n1m2 = R1 - R2 */ + secp256k1_num_sub(&n2m1, &n2, &n1); /* n2m1 = R2 - R1 */ + CHECK(secp256k1_num_eq(&n1p2, &n2p1)); + CHECK(!secp256k1_num_eq(&n1p2, &n1m2)); + secp256k1_num_negate(&n2m1); /* n2m1 = -R2 + R1 */ + CHECK(secp256k1_num_eq(&n2m1, &n1m2)); + CHECK(!secp256k1_num_eq(&n2m1, &n1)); + secp256k1_num_add(&n2m1, &n2m1, &n2); /* n2m1 = -R2 + R1 + R2 = R1 */ + CHECK(secp256k1_num_eq(&n2m1, &n1)); + CHECK(!secp256k1_num_eq(&n2p1, &n1)); + secp256k1_num_sub(&n2p1, &n2p1, &n2); /* n2p1 = R2 + R1 - R2 = R1 */ + CHECK(secp256k1_num_eq(&n2p1, &n1)); + + /* check is_one */ + secp256k1_scalar_set_int(&s, 1); + secp256k1_scalar_get_num(&n1, &s); + CHECK(secp256k1_num_is_one(&n1)); + /* check that 2^n + 1 is never 1 */ + secp256k1_scalar_get_num(&n2, &s); + for (i = 0; i < 250; ++i) { + secp256k1_num_add(&n1, &n1, &n1); /* n1 *= 2 */ + secp256k1_num_add(&n1p2, &n1, &n2); /* n1p2 = n1 + 1 */ + CHECK(!secp256k1_num_is_one(&n1p2)); + } +} + +void test_num_mod(void) { + int i; + secp256k1_scalar s; + secp256k1_num order, n; + + /* check that 0 mod anything is 0 */ + random_scalar_order_test(&s); + secp256k1_scalar_get_num(&order, &s); + secp256k1_scalar_set_int(&s, 0); + secp256k1_scalar_get_num(&n, &s); + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); + + /* check that anything mod 1 is 0 */ + secp256k1_scalar_set_int(&s, 1); + secp256k1_scalar_get_num(&order, &s); + secp256k1_scalar_get_num(&n, &s); + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); + + /* check that increasing the number past 2^256 does not break this */ + random_scalar_order_test(&s); + secp256k1_scalar_get_num(&n, &s); + /* multiply by 2^8, which'll test this case with high probability */ + for (i = 0; i < 8; ++i) { + secp256k1_num_add(&n, &n, &n); + } + secp256k1_num_mod(&n, &order); + CHECK(secp256k1_num_is_zero(&n)); +} + +void test_num_jacobi(void) { + secp256k1_scalar sqr; + secp256k1_scalar small; + secp256k1_scalar five; /* five is not a quadratic residue */ + secp256k1_num order, n; + int i; + /* squares mod 5 are 1, 4 */ + const int jacobi5[10] = { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1 }; + + /* check some small values with 5 as the order */ + secp256k1_scalar_set_int(&five, 5); + secp256k1_scalar_get_num(&order, &five); + for (i = 0; i < 10; ++i) { + secp256k1_scalar_set_int(&small, i); + secp256k1_scalar_get_num(&n, &small); + CHECK(secp256k1_num_jacobi(&n, &order) == jacobi5[i]); + } + + /** test large values with 5 as group order */ + secp256k1_scalar_get_num(&order, &five); + /* we first need a scalar which is not a multiple of 5 */ + do { + secp256k1_num fiven; + random_scalar_order_test(&sqr); + secp256k1_scalar_get_num(&fiven, &five); + secp256k1_scalar_get_num(&n, &sqr); + secp256k1_num_mod(&n, &fiven); + } while (secp256k1_num_is_zero(&n)); + /* next force it to be a residue. 2 is a nonresidue mod 5 so we can + * just multiply by two, i.e. add the number to itself */ + if (secp256k1_num_jacobi(&n, &order) == -1) { + secp256k1_num_add(&n, &n, &n); + } + + /* test residue */ + CHECK(secp256k1_num_jacobi(&n, &order) == 1); + /* test nonresidue */ + secp256k1_num_add(&n, &n, &n); + CHECK(secp256k1_num_jacobi(&n, &order) == -1); + + /** test with secp group order as order */ + secp256k1_scalar_order_get_num(&order); + random_scalar_order_test(&sqr); + secp256k1_scalar_sqr(&sqr, &sqr); + /* test residue */ + secp256k1_scalar_get_num(&n, &sqr); + CHECK(secp256k1_num_jacobi(&n, &order) == 1); + /* test nonresidue */ + secp256k1_scalar_mul(&sqr, &sqr, &five); + secp256k1_scalar_get_num(&n, &sqr); + CHECK(secp256k1_num_jacobi(&n, &order) == -1); + /* test multiple of the order*/ + CHECK(secp256k1_num_jacobi(&order, &order) == 0); + + /* check one less than the order */ + secp256k1_scalar_set_int(&small, 1); + secp256k1_scalar_get_num(&n, &small); + secp256k1_num_sub(&n, &order, &n); + CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* sage confirms this is 1 */ +} + +void run_num_smalltests(void) { + int i; + for (i = 0; i < 100*count; i++) { + test_num_negate(); + test_num_add_sub(); + test_num_mod(); + test_num_jacobi(); + } +} +#endif + +/***** SCALAR TESTS *****/ + +void scalar_test(void) { + secp256k1_scalar s; + secp256k1_scalar s1; + secp256k1_scalar s2; +#ifndef USE_NUM_NONE + secp256k1_num snum, s1num, s2num; + secp256k1_num order, half_order; +#endif + unsigned char c[32]; + + /* Set 's' to a random scalar, with value 'snum'. */ + random_scalar_order_test(&s); + + /* Set 's1' to a random scalar, with value 's1num'. */ + random_scalar_order_test(&s1); + + /* Set 's2' to a random scalar, with value 'snum2', and byte array representation 'c'. */ + random_scalar_order_test(&s2); + secp256k1_scalar_get_b32(c, &s2); + +#ifndef USE_NUM_NONE + secp256k1_scalar_get_num(&snum, &s); + secp256k1_scalar_get_num(&s1num, &s1); + secp256k1_scalar_get_num(&s2num, &s2); + + secp256k1_scalar_order_get_num(&order); + half_order = order; + secp256k1_num_shift(&half_order, 1); +#endif + + { + int i; + /* Test that fetching groups of 4 bits from a scalar and recursing n(i)=16*n(i-1)+p(i) reconstructs it. */ + secp256k1_scalar n; + secp256k1_scalar_set_int(&n, 0); + for (i = 0; i < 256; i += 4) { + secp256k1_scalar t; + int j; + secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits(&s, 256 - 4 - i, 4)); + for (j = 0; j < 4; j++) { + secp256k1_scalar_add(&n, &n, &n); + } + secp256k1_scalar_add(&n, &n, &t); + } + CHECK(secp256k1_scalar_eq(&n, &s)); + } + + { + /* Test that fetching groups of randomly-sized bits from a scalar and recursing n(i)=b*n(i-1)+p(i) reconstructs it. */ + secp256k1_scalar n; + int i = 0; + secp256k1_scalar_set_int(&n, 0); + while (i < 256) { + secp256k1_scalar t; + int j; + int now = secp256k1_rand_int(15) + 1; + if (now + i > 256) { + now = 256 - i; + } + secp256k1_scalar_set_int(&t, secp256k1_scalar_get_bits_var(&s, 256 - now - i, now)); + for (j = 0; j < now; j++) { + secp256k1_scalar_add(&n, &n, &n); + } + secp256k1_scalar_add(&n, &n, &t); + i += now; + } + CHECK(secp256k1_scalar_eq(&n, &s)); + } + +#ifndef USE_NUM_NONE + { + /* Test that adding the scalars together is equal to adding their numbers together modulo the order. */ + secp256k1_num rnum; + secp256k1_num r2num; + secp256k1_scalar r; + secp256k1_num_add(&rnum, &snum, &s2num); + secp256k1_num_mod(&rnum, &order); + secp256k1_scalar_add(&r, &s, &s2); + secp256k1_scalar_get_num(&r2num, &r); + CHECK(secp256k1_num_eq(&rnum, &r2num)); + } + + { + /* Test that multiplying the scalars is equal to multiplying their numbers modulo the order. */ + secp256k1_scalar r; + secp256k1_num r2num; + secp256k1_num rnum; + secp256k1_num_mul(&rnum, &snum, &s2num); + secp256k1_num_mod(&rnum, &order); + secp256k1_scalar_mul(&r, &s, &s2); + secp256k1_scalar_get_num(&r2num, &r); + CHECK(secp256k1_num_eq(&rnum, &r2num)); + /* The result can only be zero if at least one of the factors was zero. */ + CHECK(secp256k1_scalar_is_zero(&r) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_zero(&s2))); + /* The results can only be equal to one of the factors if that factor was zero, or the other factor was one. */ + CHECK(secp256k1_num_eq(&rnum, &snum) == (secp256k1_scalar_is_zero(&s) || secp256k1_scalar_is_one(&s2))); + CHECK(secp256k1_num_eq(&rnum, &s2num) == (secp256k1_scalar_is_zero(&s2) || secp256k1_scalar_is_one(&s))); + } + + { + secp256k1_scalar neg; + secp256k1_num negnum; + secp256k1_num negnum2; + /* Check that comparison with zero matches comparison with zero on the number. */ + CHECK(secp256k1_num_is_zero(&snum) == secp256k1_scalar_is_zero(&s)); + /* Check that comparison with the half order is equal to testing for high scalar. */ + CHECK(secp256k1_scalar_is_high(&s) == (secp256k1_num_cmp(&snum, &half_order) > 0)); + secp256k1_scalar_negate(&neg, &s); + secp256k1_num_sub(&negnum, &order, &snum); + secp256k1_num_mod(&negnum, &order); + /* Check that comparison with the half order is equal to testing for high scalar after negation. */ + CHECK(secp256k1_scalar_is_high(&neg) == (secp256k1_num_cmp(&negnum, &half_order) > 0)); + /* Negating should change the high property, unless the value was already zero. */ + CHECK((secp256k1_scalar_is_high(&s) == secp256k1_scalar_is_high(&neg)) == secp256k1_scalar_is_zero(&s)); + secp256k1_scalar_get_num(&negnum2, &neg); + /* Negating a scalar should be equal to (order - n) mod order on the number. */ + CHECK(secp256k1_num_eq(&negnum, &negnum2)); + secp256k1_scalar_add(&neg, &neg, &s); + /* Adding a number to its negation should result in zero. */ + CHECK(secp256k1_scalar_is_zero(&neg)); + secp256k1_scalar_negate(&neg, &neg); + /* Negating zero should still result in zero. */ + CHECK(secp256k1_scalar_is_zero(&neg)); + } + + { + /* Test secp256k1_scalar_mul_shift_var. */ + secp256k1_scalar r; + secp256k1_num one; + secp256k1_num rnum; + secp256k1_num rnum2; + unsigned char cone[1] = {0x01}; + unsigned int shift = 256 + secp256k1_rand_int(257); + secp256k1_scalar_mul_shift_var(&r, &s1, &s2, shift); + secp256k1_num_mul(&rnum, &s1num, &s2num); + secp256k1_num_shift(&rnum, shift - 1); + secp256k1_num_set_bin(&one, cone, 1); + secp256k1_num_add(&rnum, &rnum, &one); + secp256k1_num_shift(&rnum, 1); + secp256k1_scalar_get_num(&rnum2, &r); + CHECK(secp256k1_num_eq(&rnum, &rnum2)); + } + + { + /* test secp256k1_scalar_shr_int */ + secp256k1_scalar r; + int i; + random_scalar_order_test(&r); + for (i = 0; i < 100; ++i) { + int low; + int shift = 1 + secp256k1_rand_int(15); + int expected = r.d[0] % (1 << shift); + low = secp256k1_scalar_shr_int(&r, shift); + CHECK(expected == low); + } + } +#endif + + { + /* Test that scalar inverses are equal to the inverse of their number modulo the order. */ + if (!secp256k1_scalar_is_zero(&s)) { + secp256k1_scalar inv; +#ifndef USE_NUM_NONE + secp256k1_num invnum; + secp256k1_num invnum2; +#endif + secp256k1_scalar_inverse(&inv, &s); +#ifndef USE_NUM_NONE + secp256k1_num_mod_inverse(&invnum, &snum, &order); + secp256k1_scalar_get_num(&invnum2, &inv); + CHECK(secp256k1_num_eq(&invnum, &invnum2)); +#endif + secp256k1_scalar_mul(&inv, &inv, &s); + /* Multiplying a scalar with its inverse must result in one. */ + CHECK(secp256k1_scalar_is_one(&inv)); + secp256k1_scalar_inverse(&inv, &inv); + /* Inverting one must result in one. */ + CHECK(secp256k1_scalar_is_one(&inv)); +#ifndef USE_NUM_NONE + secp256k1_scalar_get_num(&invnum, &inv); + CHECK(secp256k1_num_is_one(&invnum)); +#endif + } + } + + { + /* Test commutativity of add. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_add(&r2, &s2, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + secp256k1_scalar r1, r2; + secp256k1_scalar b; + int i; + /* Test add_bit. */ + int bit = secp256k1_rand_bits(8); + secp256k1_scalar_set_int(&b, 1); + CHECK(secp256k1_scalar_is_one(&b)); + for (i = 0; i < bit; i++) { + secp256k1_scalar_add(&b, &b, &b); + } + r1 = s1; + r2 = s1; + if (!secp256k1_scalar_add(&r1, &r1, &b)) { + /* No overflow happened. */ + secp256k1_scalar_cadd_bit(&r2, bit, 1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + /* cadd is a noop when flag is zero */ + secp256k1_scalar_cadd_bit(&r2, bit, 0); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + } + + { + /* Test commutativity of mul. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_mul(&r1, &s1, &s2); + secp256k1_scalar_mul(&r2, &s2, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test associativity of add. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_add(&r1, &r1, &s); + secp256k1_scalar_add(&r2, &s2, &s); + secp256k1_scalar_add(&r2, &s1, &r2); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test associativity of mul. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_mul(&r1, &s1, &s2); + secp256k1_scalar_mul(&r1, &r1, &s); + secp256k1_scalar_mul(&r2, &s2, &s); + secp256k1_scalar_mul(&r2, &s1, &r2); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test distributitivity of mul over add. */ + secp256k1_scalar r1, r2, t; + secp256k1_scalar_add(&r1, &s1, &s2); + secp256k1_scalar_mul(&r1, &r1, &s); + secp256k1_scalar_mul(&r2, &s1, &s); + secp256k1_scalar_mul(&t, &s2, &s); + secp256k1_scalar_add(&r2, &r2, &t); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test square. */ + secp256k1_scalar r1, r2; + secp256k1_scalar_sqr(&r1, &s1); + secp256k1_scalar_mul(&r2, &s1, &s1); + CHECK(secp256k1_scalar_eq(&r1, &r2)); + } + + { + /* Test multiplicative identity. */ + secp256k1_scalar r1, v1; + secp256k1_scalar_set_int(&v1,1); + secp256k1_scalar_mul(&r1, &s1, &v1); + CHECK(secp256k1_scalar_eq(&r1, &s1)); + } + + { + /* Test additive identity. */ + secp256k1_scalar r1, v0; + secp256k1_scalar_set_int(&v0,0); + secp256k1_scalar_add(&r1, &s1, &v0); + CHECK(secp256k1_scalar_eq(&r1, &s1)); + } + + { + /* Test zero product property. */ + secp256k1_scalar r1, v0; + secp256k1_scalar_set_int(&v0,0); + secp256k1_scalar_mul(&r1, &s1, &v0); + CHECK(secp256k1_scalar_eq(&r1, &v0)); + } + +} + +void run_scalar_tests(void) { + int i; + for (i = 0; i < 128 * count; i++) { + scalar_test(); + } + + { + /* (-1)+1 should be zero. */ + secp256k1_scalar s, o; + secp256k1_scalar_set_int(&s, 1); + CHECK(secp256k1_scalar_is_one(&s)); + secp256k1_scalar_negate(&o, &s); + secp256k1_scalar_add(&o, &o, &s); + CHECK(secp256k1_scalar_is_zero(&o)); + secp256k1_scalar_negate(&o, &o); + CHECK(secp256k1_scalar_is_zero(&o)); + } + +#ifndef USE_NUM_NONE + { + /* A scalar with value of the curve order should be 0. */ + secp256k1_num order; + secp256k1_scalar zero; + unsigned char bin[32]; + int overflow = 0; + secp256k1_scalar_order_get_num(&order); + secp256k1_num_get_bin(bin, 32, &order); + secp256k1_scalar_set_b32(&zero, bin, &overflow); + CHECK(overflow == 1); + CHECK(secp256k1_scalar_is_zero(&zero)); + } +#endif + + { + /* Does check_overflow check catch all ones? */ + static const secp256k1_scalar overflowed = SECP256K1_SCALAR_CONST( + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, + 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL + ); + CHECK(secp256k1_scalar_check_overflow(&overflowed)); + } + + { + /* Static test vectors. + * These were reduced from ~10^12 random vectors based on comparison-decision + * and edge-case coverage on 32-bit and 64-bit implementations. + * The responses were generated with Sage 5.9. + */ + secp256k1_scalar x; + secp256k1_scalar y; + secp256k1_scalar z; + secp256k1_scalar zz; + secp256k1_scalar one; + secp256k1_scalar r1; + secp256k1_scalar r2; +#if defined(USE_SCALAR_INV_NUM) + secp256k1_scalar zzv; +#endif + int overflow; + unsigned char chal[33][2][32] = { + {{0xff, 0xff, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff}}, + {{0xef, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x80, 0xff}}, + {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x00}, + {0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x1e, 0xf8, 0xff, 0xff, 0xff, 0xfd, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xe0, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, + 0xf3, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x1c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0xfc, 0x9f, + 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0x0f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, + {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0xf8, 0xff, 0x0f, 0xc0, 0xff, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xf7, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0x00, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0}, + {0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0x00, 0xf8, 0xff, 0x03, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0xc0, 0xff, 0x0f, 0xfc, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0x8f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0f, 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, 0xc0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0x7f}, + {0xff, 0xcf, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, + 0xbf, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0x01, 0xfc, 0xff, 0x01, 0x00, 0xfe, 0xff}, + {0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00}}, + {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0x01, 0x00, 0xf0, 0xff, 0xff, + 0xe0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x00}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0x3f, 0xf0, 0xff, 0xff, 0x3f, + 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7e, 0x00, 0x00}}, + {{0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x07, 0x00}, + {0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfb, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60}}, + {{0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0x80, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0x1f, 0x00, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00}}, + {{0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xff, 0xcf, 0xff, 0x1f, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00}, + {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0x7f, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, + {0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x80, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x1f, 0x00, 0xfe}}, + {{0xff, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0x03, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 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}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}}, + {{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, 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}}, + {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff}}, + {{0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {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, 0x02}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, + {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, 0x01}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7e, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + {0xff, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}, + {{0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0xc0, 0xf1, 0x7f, 0x00}}, + {{0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x00}, + {0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, + 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0xff, 0xff}}, + {{0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0x00, 0x00, 0x80, 0xff, 0x03, 0xe0, 0x01, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, + {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0xff, 0xf0, 0x07, 0x00, 0x3c, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x07, 0xe0, 0xff, 0x00, 0x00, 0x00}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80}, + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x80, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x7f, 0xfe, 0xff, 0x1f, + 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0xfe, 0xff}}, + {{0xff, 0xff, 0x81, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, + 0xff, 0xff, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf0}, + {0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, + 0xf8, 0x07, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc7, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff}}, + {{0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, + 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}, + {0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0x82, 0xc9, 0xfa, 0xb0, 0x68, 0x04, 0xa0, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x03, 0xfb, + 0xfa, 0x8a, 0x7d, 0xdf, 0x13, 0x86, 0xe2, 0x03}} + }; + unsigned char res[33][2][32] = { + {{0x0c, 0x3b, 0x0a, 0xca, 0x8d, 0x1a, 0x2f, 0xb9, + 0x8a, 0x7b, 0x53, 0x5a, 0x1f, 0xc5, 0x22, 0xa1, + 0x07, 0x2a, 0x48, 0xea, 0x02, 0xeb, 0xb3, 0xd6, + 0x20, 0x1e, 0x86, 0xd0, 0x95, 0xf6, 0x92, 0x35}, + {0xdc, 0x90, 0x7a, 0x07, 0x2e, 0x1e, 0x44, 0x6d, + 0xf8, 0x15, 0x24, 0x5b, 0x5a, 0x96, 0x37, 0x9c, + 0x37, 0x7b, 0x0d, 0xac, 0x1b, 0x65, 0x58, 0x49, + 0x43, 0xb7, 0x31, 0xbb, 0xa7, 0xf4, 0x97, 0x15}}, + {{0xf1, 0xf7, 0x3a, 0x50, 0xe6, 0x10, 0xba, 0x22, + 0x43, 0x4d, 0x1f, 0x1f, 0x7c, 0x27, 0xca, 0x9c, + 0xb8, 0xb6, 0xa0, 0xfc, 0xd8, 0xc0, 0x05, 0x2f, + 0xf7, 0x08, 0xe1, 0x76, 0xdd, 0xd0, 0x80, 0xc8}, + {0xe3, 0x80, 0x80, 0xb8, 0xdb, 0xe3, 0xa9, 0x77, + 0x00, 0xb0, 0xf5, 0x2e, 0x27, 0xe2, 0x68, 0xc4, + 0x88, 0xe8, 0x04, 0xc1, 0x12, 0xbf, 0x78, 0x59, + 0xe6, 0xa9, 0x7c, 0xe1, 0x81, 0xdd, 0xb9, 0xd5}}, + {{0x96, 0xe2, 0xee, 0x01, 0xa6, 0x80, 0x31, 0xef, + 0x5c, 0xd0, 0x19, 0xb4, 0x7d, 0x5f, 0x79, 0xab, + 0xa1, 0x97, 0xd3, 0x7e, 0x33, 0xbb, 0x86, 0x55, + 0x60, 0x20, 0x10, 0x0d, 0x94, 0x2d, 0x11, 0x7c}, + {0xcc, 0xab, 0xe0, 0xe8, 0x98, 0x65, 0x12, 0x96, + 0x38, 0x5a, 0x1a, 0xf2, 0x85, 0x23, 0x59, 0x5f, + 0xf9, 0xf3, 0xc2, 0x81, 0x70, 0x92, 0x65, 0x12, + 0x9c, 0x65, 0x1e, 0x96, 0x00, 0xef, 0xe7, 0x63}}, + {{0xac, 0x1e, 0x62, 0xc2, 0x59, 0xfc, 0x4e, 0x5c, + 0x83, 0xb0, 0xd0, 0x6f, 0xce, 0x19, 0xf6, 0xbf, + 0xa4, 0xb0, 0xe0, 0x53, 0x66, 0x1f, 0xbf, 0xc9, + 0x33, 0x47, 0x37, 0xa9, 0x3d, 0x5d, 0xb0, 0x48}, + {0x86, 0xb9, 0x2a, 0x7f, 0x8e, 0xa8, 0x60, 0x42, + 0x26, 0x6d, 0x6e, 0x1c, 0xa2, 0xec, 0xe0, 0xe5, + 0x3e, 0x0a, 0x33, 0xbb, 0x61, 0x4c, 0x9f, 0x3c, + 0xd1, 0xdf, 0x49, 0x33, 0xcd, 0x72, 0x78, 0x18}}, + {{0xf7, 0xd3, 0xcd, 0x49, 0x5c, 0x13, 0x22, 0xfb, + 0x2e, 0xb2, 0x2f, 0x27, 0xf5, 0x8a, 0x5d, 0x74, + 0xc1, 0x58, 0xc5, 0xc2, 0x2d, 0x9f, 0x52, 0xc6, + 0x63, 0x9f, 0xba, 0x05, 0x76, 0x45, 0x7a, 0x63}, + {0x8a, 0xfa, 0x55, 0x4d, 0xdd, 0xa3, 0xb2, 0xc3, + 0x44, 0xfd, 0xec, 0x72, 0xde, 0xef, 0xc0, 0x99, + 0xf5, 0x9f, 0xe2, 0x52, 0xb4, 0x05, 0x32, 0x58, + 0x57, 0xc1, 0x8f, 0xea, 0xc3, 0x24, 0x5b, 0x94}}, + {{0x05, 0x83, 0xee, 0xdd, 0x64, 0xf0, 0x14, 0x3b, + 0xa0, 0x14, 0x4a, 0x3a, 0x41, 0x82, 0x7c, 0xa7, + 0x2c, 0xaa, 0xb1, 0x76, 0xbb, 0x59, 0x64, 0x5f, + 0x52, 0xad, 0x25, 0x29, 0x9d, 0x8f, 0x0b, 0xb0}, + {0x7e, 0xe3, 0x7c, 0xca, 0xcd, 0x4f, 0xb0, 0x6d, + 0x7a, 0xb2, 0x3e, 0xa0, 0x08, 0xb9, 0xa8, 0x2d, + 0xc2, 0xf4, 0x99, 0x66, 0xcc, 0xac, 0xd8, 0xb9, + 0x72, 0x2a, 0x4a, 0x3e, 0x0f, 0x7b, 0xbf, 0xf4}}, + {{0x8c, 0x9c, 0x78, 0x2b, 0x39, 0x61, 0x7e, 0xf7, + 0x65, 0x37, 0x66, 0x09, 0x38, 0xb9, 0x6f, 0x70, + 0x78, 0x87, 0xff, 0xcf, 0x93, 0xca, 0x85, 0x06, + 0x44, 0x84, 0xa7, 0xfe, 0xd3, 0xa4, 0xe3, 0x7e}, + {0xa2, 0x56, 0x49, 0x23, 0x54, 0xa5, 0x50, 0xe9, + 0x5f, 0xf0, 0x4d, 0xe7, 0xdc, 0x38, 0x32, 0x79, + 0x4f, 0x1c, 0xb7, 0xe4, 0xbb, 0xf8, 0xbb, 0x2e, + 0x40, 0x41, 0x4b, 0xcc, 0xe3, 0x1e, 0x16, 0x36}}, + {{0x0c, 0x1e, 0xd7, 0x09, 0x25, 0x40, 0x97, 0xcb, + 0x5c, 0x46, 0xa8, 0xda, 0xef, 0x25, 0xd5, 0xe5, + 0x92, 0x4d, 0xcf, 0xa3, 0xc4, 0x5d, 0x35, 0x4a, + 0xe4, 0x61, 0x92, 0xf3, 0xbf, 0x0e, 0xcd, 0xbe}, + {0xe4, 0xaf, 0x0a, 0xb3, 0x30, 0x8b, 0x9b, 0x48, + 0x49, 0x43, 0xc7, 0x64, 0x60, 0x4a, 0x2b, 0x9e, + 0x95, 0x5f, 0x56, 0xe8, 0x35, 0xdc, 0xeb, 0xdc, + 0xc7, 0xc4, 0xfe, 0x30, 0x40, 0xc7, 0xbf, 0xa4}}, + {{0xd4, 0xa0, 0xf5, 0x81, 0x49, 0x6b, 0xb6, 0x8b, + 0x0a, 0x69, 0xf9, 0xfe, 0xa8, 0x32, 0xe5, 0xe0, + 0xa5, 0xcd, 0x02, 0x53, 0xf9, 0x2c, 0xe3, 0x53, + 0x83, 0x36, 0xc6, 0x02, 0xb5, 0xeb, 0x64, 0xb8}, + {0x1d, 0x42, 0xb9, 0xf9, 0xe9, 0xe3, 0x93, 0x2c, + 0x4c, 0xee, 0x6c, 0x5a, 0x47, 0x9e, 0x62, 0x01, + 0x6b, 0x04, 0xfe, 0xa4, 0x30, 0x2b, 0x0d, 0x4f, + 0x71, 0x10, 0xd3, 0x55, 0xca, 0xf3, 0x5e, 0x80}}, + {{0x77, 0x05, 0xf6, 0x0c, 0x15, 0x9b, 0x45, 0xe7, + 0xb9, 0x11, 0xb8, 0xf5, 0xd6, 0xda, 0x73, 0x0c, + 0xda, 0x92, 0xea, 0xd0, 0x9d, 0xd0, 0x18, 0x92, + 0xce, 0x9a, 0xaa, 0xee, 0x0f, 0xef, 0xde, 0x30}, + {0xf1, 0xf1, 0xd6, 0x9b, 0x51, 0xd7, 0x77, 0x62, + 0x52, 0x10, 0xb8, 0x7a, 0x84, 0x9d, 0x15, 0x4e, + 0x07, 0xdc, 0x1e, 0x75, 0x0d, 0x0c, 0x3b, 0xdb, + 0x74, 0x58, 0x62, 0x02, 0x90, 0x54, 0x8b, 0x43}}, + {{0xa6, 0xfe, 0x0b, 0x87, 0x80, 0x43, 0x67, 0x25, + 0x57, 0x5d, 0xec, 0x40, 0x50, 0x08, 0xd5, 0x5d, + 0x43, 0xd7, 0xe0, 0xaa, 0xe0, 0x13, 0xb6, 0xb0, + 0xc0, 0xd4, 0xe5, 0x0d, 0x45, 0x83, 0xd6, 0x13}, + {0x40, 0x45, 0x0a, 0x92, 0x31, 0xea, 0x8c, 0x60, + 0x8c, 0x1f, 0xd8, 0x76, 0x45, 0xb9, 0x29, 0x00, + 0x26, 0x32, 0xd8, 0xa6, 0x96, 0x88, 0xe2, 0xc4, + 0x8b, 0xdb, 0x7f, 0x17, 0x87, 0xcc, 0xc8, 0xf2}}, + {{0xc2, 0x56, 0xe2, 0xb6, 0x1a, 0x81, 0xe7, 0x31, + 0x63, 0x2e, 0xbb, 0x0d, 0x2f, 0x81, 0x67, 0xd4, + 0x22, 0xe2, 0x38, 0x02, 0x25, 0x97, 0xc7, 0x88, + 0x6e, 0xdf, 0xbe, 0x2a, 0xa5, 0x73, 0x63, 0xaa}, + {0x50, 0x45, 0xe2, 0xc3, 0xbd, 0x89, 0xfc, 0x57, + 0xbd, 0x3c, 0xa3, 0x98, 0x7e, 0x7f, 0x36, 0x38, + 0x92, 0x39, 0x1f, 0x0f, 0x81, 0x1a, 0x06, 0x51, + 0x1f, 0x8d, 0x6a, 0xff, 0x47, 0x16, 0x06, 0x9c}}, + {{0x33, 0x95, 0xa2, 0x6f, 0x27, 0x5f, 0x9c, 0x9c, + 0x64, 0x45, 0xcb, 0xd1, 0x3c, 0xee, 0x5e, 0x5f, + 0x48, 0xa6, 0xaf, 0xe3, 0x79, 0xcf, 0xb1, 0xe2, + 0xbf, 0x55, 0x0e, 0xa2, 0x3b, 0x62, 0xf0, 0xe4}, + {0x14, 0xe8, 0x06, 0xe3, 0xbe, 0x7e, 0x67, 0x01, + 0xc5, 0x21, 0x67, 0xd8, 0x54, 0xb5, 0x7f, 0xa4, + 0xf9, 0x75, 0x70, 0x1c, 0xfd, 0x79, 0xdb, 0x86, + 0xad, 0x37, 0x85, 0x83, 0x56, 0x4e, 0xf0, 0xbf}}, + {{0xbc, 0xa6, 0xe0, 0x56, 0x4e, 0xef, 0xfa, 0xf5, + 0x1d, 0x5d, 0x3f, 0x2a, 0x5b, 0x19, 0xab, 0x51, + 0xc5, 0x8b, 0xdd, 0x98, 0x28, 0x35, 0x2f, 0xc3, + 0x81, 0x4f, 0x5c, 0xe5, 0x70, 0xb9, 0xeb, 0x62}, + {0xc4, 0x6d, 0x26, 0xb0, 0x17, 0x6b, 0xfe, 0x6c, + 0x12, 0xf8, 0xe7, 0xc1, 0xf5, 0x2f, 0xfa, 0x91, + 0x13, 0x27, 0xbd, 0x73, 0xcc, 0x33, 0x31, 0x1c, + 0x39, 0xe3, 0x27, 0x6a, 0x95, 0xcf, 0xc5, 0xfb}}, + {{0x30, 0xb2, 0x99, 0x84, 0xf0, 0x18, 0x2a, 0x6e, + 0x1e, 0x27, 0xed, 0xa2, 0x29, 0x99, 0x41, 0x56, + 0xe8, 0xd4, 0x0d, 0xef, 0x99, 0x9c, 0xf3, 0x58, + 0x29, 0x55, 0x1a, 0xc0, 0x68, 0xd6, 0x74, 0xa4}, + {0x07, 0x9c, 0xe7, 0xec, 0xf5, 0x36, 0x73, 0x41, + 0xa3, 0x1c, 0xe5, 0x93, 0x97, 0x6a, 0xfd, 0xf7, + 0x53, 0x18, 0xab, 0xaf, 0xeb, 0x85, 0xbd, 0x92, + 0x90, 0xab, 0x3c, 0xbf, 0x30, 0x82, 0xad, 0xf6}}, + {{0xc6, 0x87, 0x8a, 0x2a, 0xea, 0xc0, 0xa9, 0xec, + 0x6d, 0xd3, 0xdc, 0x32, 0x23, 0xce, 0x62, 0x19, + 0xa4, 0x7e, 0xa8, 0xdd, 0x1c, 0x33, 0xae, 0xd3, + 0x4f, 0x62, 0x9f, 0x52, 0xe7, 0x65, 0x46, 0xf4}, + {0x97, 0x51, 0x27, 0x67, 0x2d, 0xa2, 0x82, 0x87, + 0x98, 0xd3, 0xb6, 0x14, 0x7f, 0x51, 0xd3, 0x9a, + 0x0b, 0xd0, 0x76, 0x81, 0xb2, 0x4f, 0x58, 0x92, + 0xa4, 0x86, 0xa1, 0xa7, 0x09, 0x1d, 0xef, 0x9b}}, + {{0xb3, 0x0f, 0x2b, 0x69, 0x0d, 0x06, 0x90, 0x64, + 0xbd, 0x43, 0x4c, 0x10, 0xe8, 0x98, 0x1c, 0xa3, + 0xe1, 0x68, 0xe9, 0x79, 0x6c, 0x29, 0x51, 0x3f, + 0x41, 0xdc, 0xdf, 0x1f, 0xf3, 0x60, 0xbe, 0x33}, + {0xa1, 0x5f, 0xf7, 0x1d, 0xb4, 0x3e, 0x9b, 0x3c, + 0xe7, 0xbd, 0xb6, 0x06, 0xd5, 0x60, 0x06, 0x6d, + 0x50, 0xd2, 0xf4, 0x1a, 0x31, 0x08, 0xf2, 0xea, + 0x8e, 0xef, 0x5f, 0x7d, 0xb6, 0xd0, 0xc0, 0x27}}, + {{0x62, 0x9a, 0xd9, 0xbb, 0x38, 0x36, 0xce, 0xf7, + 0x5d, 0x2f, 0x13, 0xec, 0xc8, 0x2d, 0x02, 0x8a, + 0x2e, 0x72, 0xf0, 0xe5, 0x15, 0x9d, 0x72, 0xae, + 0xfc, 0xb3, 0x4f, 0x02, 0xea, 0xe1, 0x09, 0xfe}, + {0x00, 0x00, 0x00, 0x00, 0xfa, 0x0a, 0x3d, 0xbc, + 0xad, 0x16, 0x0c, 0xb6, 0xe7, 0x7c, 0x8b, 0x39, + 0x9a, 0x43, 0xbb, 0xe3, 0xc2, 0x55, 0x15, 0x14, + 0x75, 0xac, 0x90, 0x9b, 0x7f, 0x9a, 0x92, 0x00}}, + {{0x8b, 0xac, 0x70, 0x86, 0x29, 0x8f, 0x00, 0x23, + 0x7b, 0x45, 0x30, 0xaa, 0xb8, 0x4c, 0xc7, 0x8d, + 0x4e, 0x47, 0x85, 0xc6, 0x19, 0xe3, 0x96, 0xc2, + 0x9a, 0xa0, 0x12, 0xed, 0x6f, 0xd7, 0x76, 0x16}, + {0x45, 0xaf, 0x7e, 0x33, 0xc7, 0x7f, 0x10, 0x6c, + 0x7c, 0x9f, 0x29, 0xc1, 0xa8, 0x7e, 0x15, 0x84, + 0xe7, 0x7d, 0xc0, 0x6d, 0xab, 0x71, 0x5d, 0xd0, + 0x6b, 0x9f, 0x97, 0xab, 0xcb, 0x51, 0x0c, 0x9f}}, + {{0x9e, 0xc3, 0x92, 0xb4, 0x04, 0x9f, 0xc8, 0xbb, + 0xdd, 0x9e, 0xc6, 0x05, 0xfd, 0x65, 0xec, 0x94, + 0x7f, 0x2c, 0x16, 0xc4, 0x40, 0xac, 0x63, 0x7b, + 0x7d, 0xb8, 0x0c, 0xe4, 0x5b, 0xe3, 0xa7, 0x0e}, + {0x43, 0xf4, 0x44, 0xe8, 0xcc, 0xc8, 0xd4, 0x54, + 0x33, 0x37, 0x50, 0xf2, 0x87, 0x42, 0x2e, 0x00, + 0x49, 0x60, 0x62, 0x02, 0xfd, 0x1a, 0x7c, 0xdb, + 0x29, 0x6c, 0x6d, 0x54, 0x53, 0x08, 0xd1, 0xc8}}, + {{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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}}, + {{0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, + 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, + 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, + 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}, + {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, + 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, + 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, + 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, + {{0x28, 0x56, 0xac, 0x0e, 0x4f, 0x98, 0x09, 0xf0, + 0x49, 0xfa, 0x7f, 0x84, 0xac, 0x7e, 0x50, 0x5b, + 0x17, 0x43, 0x14, 0x89, 0x9c, 0x53, 0xa8, 0x94, + 0x30, 0xf2, 0x11, 0x4d, 0x92, 0x14, 0x27, 0xe8}, + {0x39, 0x7a, 0x84, 0x56, 0x79, 0x9d, 0xec, 0x26, + 0x2c, 0x53, 0xc1, 0x94, 0xc9, 0x8d, 0x9e, 0x9d, + 0x32, 0x1f, 0xdd, 0x84, 0x04, 0xe8, 0xe2, 0x0a, + 0x6b, 0xbe, 0xbb, 0x42, 0x40, 0x67, 0x30, 0x6c}}, + {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, + 0x40, 0x2d, 0xa1, 0x73, 0x2f, 0xc9, 0xbe, 0xbd}, + {0x27, 0x59, 0xc7, 0x35, 0x60, 0x71, 0xa6, 0xf1, + 0x79, 0xa5, 0xfd, 0x79, 0x16, 0xf3, 0x41, 0xf0, + 0x57, 0xb4, 0x02, 0x97, 0x32, 0xe7, 0xde, 0x59, + 0xe2, 0x2d, 0x9b, 0x11, 0xea, 0x2c, 0x35, 0x92}}, + {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40}, + {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, 0x01}}, + {{0x1c, 0xc4, 0xf7, 0xda, 0x0f, 0x65, 0xca, 0x39, + 0x70, 0x52, 0x92, 0x8e, 0xc3, 0xc8, 0x15, 0xea, + 0x7f, 0x10, 0x9e, 0x77, 0x4b, 0x6e, 0x2d, 0xdf, + 0xe8, 0x30, 0x9d, 0xda, 0xe8, 0x9a, 0x65, 0xae}, + {0x02, 0xb0, 0x16, 0xb1, 0x1d, 0xc8, 0x57, 0x7b, + 0xa2, 0x3a, 0xa2, 0xa3, 0x38, 0x5c, 0x8f, 0xeb, + 0x66, 0x37, 0x91, 0xa8, 0x5f, 0xef, 0x04, 0xf6, + 0x59, 0x75, 0xe1, 0xee, 0x92, 0xf6, 0x0e, 0x30}}, + {{0x8d, 0x76, 0x14, 0xa4, 0x14, 0x06, 0x9f, 0x9a, + 0xdf, 0x4a, 0x85, 0xa7, 0x6b, 0xbf, 0x29, 0x6f, + 0xbc, 0x34, 0x87, 0x5d, 0xeb, 0xbb, 0x2e, 0xa9, + 0xc9, 0x1f, 0x58, 0xd6, 0x9a, 0x82, 0xa0, 0x56}, + {0xd4, 0xb9, 0xdb, 0x88, 0x1d, 0x04, 0xe9, 0x93, + 0x8d, 0x3f, 0x20, 0xd5, 0x86, 0xa8, 0x83, 0x07, + 0xdb, 0x09, 0xd8, 0x22, 0x1f, 0x7f, 0xf1, 0x71, + 0xc8, 0xe7, 0x5d, 0x47, 0xaf, 0x8b, 0x72, 0xe9}}, + {{0x83, 0xb9, 0x39, 0xb2, 0xa4, 0xdf, 0x46, 0x87, + 0xc2, 0xb8, 0xf1, 0xe6, 0x4c, 0xd1, 0xe2, 0xa9, + 0xe4, 0x70, 0x30, 0x34, 0xbc, 0x52, 0x7c, 0x55, + 0xa6, 0xec, 0x80, 0xa4, 0xe5, 0xd2, 0xdc, 0x73}, + {0x08, 0xf1, 0x03, 0xcf, 0x16, 0x73, 0xe8, 0x7d, + 0xb6, 0x7e, 0x9b, 0xc0, 0xb4, 0xc2, 0xa5, 0x86, + 0x02, 0x77, 0xd5, 0x27, 0x86, 0xa5, 0x15, 0xfb, + 0xae, 0x9b, 0x8c, 0xa9, 0xf9, 0xf8, 0xa8, 0x4a}}, + {{0x8b, 0x00, 0x49, 0xdb, 0xfa, 0xf0, 0x1b, 0xa2, + 0xed, 0x8a, 0x9a, 0x7a, 0x36, 0x78, 0x4a, 0xc7, + 0xf7, 0xad, 0x39, 0xd0, 0x6c, 0x65, 0x7a, 0x41, + 0xce, 0xd6, 0xd6, 0x4c, 0x20, 0x21, 0x6b, 0xc7}, + {0xc6, 0xca, 0x78, 0x1d, 0x32, 0x6c, 0x6c, 0x06, + 0x91, 0xf2, 0x1a, 0xe8, 0x43, 0x16, 0xea, 0x04, + 0x3c, 0x1f, 0x07, 0x85, 0xf7, 0x09, 0x22, 0x08, + 0xba, 0x13, 0xfd, 0x78, 0x1e, 0x3f, 0x6f, 0x62}}, + {{0x25, 0x9b, 0x7c, 0xb0, 0xac, 0x72, 0x6f, 0xb2, + 0xe3, 0x53, 0x84, 0x7a, 0x1a, 0x9a, 0x98, 0x9b, + 0x44, 0xd3, 0x59, 0xd0, 0x8e, 0x57, 0x41, 0x40, + 0x78, 0xa7, 0x30, 0x2f, 0x4c, 0x9c, 0xb9, 0x68}, + {0xb7, 0x75, 0x03, 0x63, 0x61, 0xc2, 0x48, 0x6e, + 0x12, 0x3d, 0xbf, 0x4b, 0x27, 0xdf, 0xb1, 0x7a, + 0xff, 0x4e, 0x31, 0x07, 0x83, 0xf4, 0x62, 0x5b, + 0x19, 0xa5, 0xac, 0xa0, 0x32, 0x58, 0x0d, 0xa7}}, + {{0x43, 0x4f, 0x10, 0xa4, 0xca, 0xdb, 0x38, 0x67, + 0xfa, 0xae, 0x96, 0xb5, 0x6d, 0x97, 0xff, 0x1f, + 0xb6, 0x83, 0x43, 0xd3, 0xa0, 0x2d, 0x70, 0x7a, + 0x64, 0x05, 0x4c, 0xa7, 0xc1, 0xa5, 0x21, 0x51}, + {0xe4, 0xf1, 0x23, 0x84, 0xe1, 0xb5, 0x9d, 0xf2, + 0xb8, 0x73, 0x8b, 0x45, 0x2b, 0x35, 0x46, 0x38, + 0x10, 0x2b, 0x50, 0xf8, 0x8b, 0x35, 0xcd, 0x34, + 0xc8, 0x0e, 0xf6, 0xdb, 0x09, 0x35, 0xf0, 0xda}}, + {{0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, + 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, + 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, + 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}, + {0xdb, 0x21, 0x5c, 0x8d, 0x83, 0x1d, 0xb3, 0x34, + 0xc7, 0x0e, 0x43, 0xa1, 0x58, 0x79, 0x67, 0x13, + 0x1e, 0x86, 0x5d, 0x89, 0x63, 0xe6, 0x0a, 0x46, + 0x5c, 0x02, 0x97, 0x1b, 0x62, 0x43, 0x86, 0xf5}} + }; + secp256k1_scalar_set_int(&one, 1); + for (i = 0; i < 33; i++) { + secp256k1_scalar_set_b32(&x, chal[i][0], &overflow); + CHECK(!overflow); + secp256k1_scalar_set_b32(&y, chal[i][1], &overflow); + CHECK(!overflow); + secp256k1_scalar_set_b32(&r1, res[i][0], &overflow); + CHECK(!overflow); + secp256k1_scalar_set_b32(&r2, res[i][1], &overflow); + CHECK(!overflow); + secp256k1_scalar_mul(&z, &x, &y); + CHECK(!secp256k1_scalar_check_overflow(&z)); + CHECK(secp256k1_scalar_eq(&r1, &z)); + if (!secp256k1_scalar_is_zero(&y)) { + secp256k1_scalar_inverse(&zz, &y); + CHECK(!secp256k1_scalar_check_overflow(&zz)); +#if defined(USE_SCALAR_INV_NUM) + secp256k1_scalar_inverse_var(&zzv, &y); + CHECK(secp256k1_scalar_eq(&zzv, &zz)); +#endif + secp256k1_scalar_mul(&z, &z, &zz); + CHECK(!secp256k1_scalar_check_overflow(&z)); + CHECK(secp256k1_scalar_eq(&x, &z)); + secp256k1_scalar_mul(&zz, &zz, &y); + CHECK(!secp256k1_scalar_check_overflow(&zz)); + CHECK(secp256k1_scalar_eq(&one, &zz)); + } + secp256k1_scalar_mul(&z, &x, &x); + CHECK(!secp256k1_scalar_check_overflow(&z)); + secp256k1_scalar_sqr(&zz, &x); + CHECK(!secp256k1_scalar_check_overflow(&zz)); + CHECK(secp256k1_scalar_eq(&zz, &z)); + CHECK(secp256k1_scalar_eq(&r2, &zz)); + } + } +} + +/***** FIELD TESTS *****/ + +void random_fe(secp256k1_fe *x) { + unsigned char bin[32]; + do { + secp256k1_rand256(bin); + if (secp256k1_fe_set_b32(x, bin)) { + return; + } + } while(1); +} + +void random_fe_test(secp256k1_fe *x) { + unsigned char bin[32]; + do { + secp256k1_rand256_test(bin); + if (secp256k1_fe_set_b32(x, bin)) { + return; + } + } while(1); +} + +void random_fe_non_zero(secp256k1_fe *nz) { + int tries = 10; + while (--tries >= 0) { + random_fe(nz); + secp256k1_fe_normalize(nz); + if (!secp256k1_fe_is_zero(nz)) { + break; + } + } + /* Infinitesimal probability of spurious failure here */ + CHECK(tries >= 0); +} + +void random_fe_non_square(secp256k1_fe *ns) { + secp256k1_fe r; + random_fe_non_zero(ns); + if (secp256k1_fe_sqrt(&r, ns)) { + secp256k1_fe_negate(ns, ns, 1); + } +} + +int check_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe an = *a; + secp256k1_fe bn = *b; + secp256k1_fe_normalize_weak(&an); + secp256k1_fe_normalize_var(&bn); + return secp256k1_fe_equal_var(&an, &bn); +} + +int check_fe_inverse(const secp256k1_fe *a, const secp256k1_fe *ai) { + secp256k1_fe x; + secp256k1_fe one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_fe_mul(&x, a, ai); + return check_fe_equal(&x, &one); +} + +void run_field_convert(void) { + static const unsigned char b32[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x40 + }; + static const secp256k1_fe_storage fes = SECP256K1_FE_STORAGE_CONST( + 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, + 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL + ); + static const secp256k1_fe fe = SECP256K1_FE_CONST( + 0x00010203UL, 0x04050607UL, 0x11121314UL, 0x15161718UL, + 0x22232425UL, 0x26272829UL, 0x33343536UL, 0x37383940UL + ); + secp256k1_fe fe2; + unsigned char b322[32]; + secp256k1_fe_storage fes2; + /* Check conversions to fe. */ + CHECK(secp256k1_fe_set_b32(&fe2, b32)); + CHECK(secp256k1_fe_equal_var(&fe, &fe2)); + secp256k1_fe_from_storage(&fe2, &fes); + CHECK(secp256k1_fe_equal_var(&fe, &fe2)); + /* Check conversion from fe. */ + secp256k1_fe_get_b32(b322, &fe); + CHECK(memcmp(b322, b32, 32) == 0); + secp256k1_fe_to_storage(&fes2, &fe); + CHECK(memcmp(&fes2, &fes, sizeof(fes)) == 0); +} + +int fe_memcmp(const secp256k1_fe *a, const secp256k1_fe *b) { + secp256k1_fe t = *b; +#ifdef VERIFY + t.magnitude = a->magnitude; + t.normalized = a->normalized; +#endif + return memcmp(a, &t, sizeof(secp256k1_fe)); +} + +void run_field_misc(void) { + secp256k1_fe x; + secp256k1_fe y; + secp256k1_fe z; + secp256k1_fe q; + secp256k1_fe fe5 = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 5); + int i, j; + for (i = 0; i < 5*count; i++) { + secp256k1_fe_storage xs, ys, zs; + random_fe(&x); + random_fe_non_zero(&y); + /* Test the fe equality and comparison operations. */ + CHECK(secp256k1_fe_cmp_var(&x, &x) == 0); + CHECK(secp256k1_fe_equal_var(&x, &x)); + z = x; + secp256k1_fe_add(&z,&y); + /* Test fe conditional move; z is not normalized here. */ + q = x; + secp256k1_fe_cmov(&x, &z, 0); + VERIFY_CHECK(!x.normalized && x.magnitude == z.magnitude); + secp256k1_fe_cmov(&x, &x, 1); + CHECK(fe_memcmp(&x, &z) != 0); + CHECK(fe_memcmp(&x, &q) == 0); + secp256k1_fe_cmov(&q, &z, 1); + VERIFY_CHECK(!q.normalized && q.magnitude == z.magnitude); + CHECK(fe_memcmp(&q, &z) == 0); + secp256k1_fe_normalize_var(&x); + secp256k1_fe_normalize_var(&z); + CHECK(!secp256k1_fe_equal_var(&x, &z)); + secp256k1_fe_normalize_var(&q); + secp256k1_fe_cmov(&q, &z, (i&1)); + VERIFY_CHECK(q.normalized && q.magnitude == 1); + for (j = 0; j < 6; j++) { + secp256k1_fe_negate(&z, &z, j+1); + secp256k1_fe_normalize_var(&q); + secp256k1_fe_cmov(&q, &z, (j&1)); + VERIFY_CHECK(!q.normalized && q.magnitude == (j+2)); + } + secp256k1_fe_normalize_var(&z); + /* Test storage conversion and conditional moves. */ + secp256k1_fe_to_storage(&xs, &x); + secp256k1_fe_to_storage(&ys, &y); + secp256k1_fe_to_storage(&zs, &z); + secp256k1_fe_storage_cmov(&zs, &xs, 0); + secp256k1_fe_storage_cmov(&zs, &zs, 1); + CHECK(memcmp(&xs, &zs, sizeof(xs)) != 0); + secp256k1_fe_storage_cmov(&ys, &xs, 1); + CHECK(memcmp(&xs, &ys, sizeof(xs)) == 0); + secp256k1_fe_from_storage(&x, &xs); + secp256k1_fe_from_storage(&y, &ys); + secp256k1_fe_from_storage(&z, &zs); + /* Test that mul_int, mul, and add agree. */ + secp256k1_fe_add(&y, &x); + secp256k1_fe_add(&y, &x); + z = x; + secp256k1_fe_mul_int(&z, 3); + CHECK(check_fe_equal(&y, &z)); + secp256k1_fe_add(&y, &x); + secp256k1_fe_add(&z, &x); + CHECK(check_fe_equal(&z, &y)); + z = x; + secp256k1_fe_mul_int(&z, 5); + secp256k1_fe_mul(&q, &x, &fe5); + CHECK(check_fe_equal(&z, &q)); + secp256k1_fe_negate(&x, &x, 1); + secp256k1_fe_add(&z, &x); + secp256k1_fe_add(&q, &x); + CHECK(check_fe_equal(&y, &z)); + CHECK(check_fe_equal(&q, &y)); + } +} + +void run_field_inv(void) { + secp256k1_fe x, xi, xii; + int i; + for (i = 0; i < 10*count; i++) { + random_fe_non_zero(&x); + secp256k1_fe_inv(&xi, &x); + CHECK(check_fe_inverse(&x, &xi)); + secp256k1_fe_inv(&xii, &xi); + CHECK(check_fe_equal(&x, &xii)); + } +} + +void run_field_inv_var(void) { + secp256k1_fe x, xi, xii; + int i; + for (i = 0; i < 10*count; i++) { + random_fe_non_zero(&x); + secp256k1_fe_inv_var(&xi, &x); + CHECK(check_fe_inverse(&x, &xi)); + secp256k1_fe_inv_var(&xii, &xi); + CHECK(check_fe_equal(&x, &xii)); + } +} + +void run_field_inv_all_var(void) { + secp256k1_fe x[16], xi[16], xii[16]; + int i; + /* Check it's safe to call for 0 elements */ + secp256k1_fe_inv_all_var(xi, x, 0); + for (i = 0; i < count; i++) { + size_t j; + size_t len = secp256k1_rand_int(15) + 1; + for (j = 0; j < len; j++) { + random_fe_non_zero(&x[j]); + } + secp256k1_fe_inv_all_var(xi, x, len); + for (j = 0; j < len; j++) { + CHECK(check_fe_inverse(&x[j], &xi[j])); + } + secp256k1_fe_inv_all_var(xii, xi, len); + for (j = 0; j < len; j++) { + CHECK(check_fe_equal(&x[j], &xii[j])); + } + } +} + +void run_sqr(void) { + secp256k1_fe x, s; + + { + int i; + secp256k1_fe_set_int(&x, 1); + secp256k1_fe_negate(&x, &x, 1); + + for (i = 1; i <= 512; ++i) { + secp256k1_fe_mul_int(&x, 2); + secp256k1_fe_normalize(&x); + secp256k1_fe_sqr(&s, &x); + } + } +} + +void test_sqrt(const secp256k1_fe *a, const secp256k1_fe *k) { + secp256k1_fe r1, r2; + int v = secp256k1_fe_sqrt(&r1, a); + CHECK((v == 0) == (k == NULL)); + + if (k != NULL) { + /* Check that the returned root is +/- the given known answer */ + secp256k1_fe_negate(&r2, &r1, 1); + secp256k1_fe_add(&r1, k); secp256k1_fe_add(&r2, k); + secp256k1_fe_normalize(&r1); secp256k1_fe_normalize(&r2); + CHECK(secp256k1_fe_is_zero(&r1) || secp256k1_fe_is_zero(&r2)); + } +} + +void run_sqrt(void) { + secp256k1_fe ns, x, s, t; + int i; + + /* Check sqrt(0) is 0 */ + secp256k1_fe_set_int(&x, 0); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + + /* Check sqrt of small squares (and their negatives) */ + for (i = 1; i <= 100; i++) { + secp256k1_fe_set_int(&x, i); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + secp256k1_fe_negate(&t, &s, 1); + test_sqrt(&t, NULL); + } + + /* Consistency checks for large random values */ + for (i = 0; i < 10; i++) { + int j; + random_fe_non_square(&ns); + for (j = 0; j < count; j++) { + random_fe(&x); + secp256k1_fe_sqr(&s, &x); + test_sqrt(&s, &x); + secp256k1_fe_negate(&t, &s, 1); + test_sqrt(&t, NULL); + secp256k1_fe_mul(&t, &s, &ns); + test_sqrt(&t, NULL); + } + } +} + +/***** GROUP TESTS *****/ + +void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); + CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); +} + +/* This compares jacobian points including their Z, not just their geometric meaning. */ +int gej_xyz_equals_gej(const secp256k1_gej *a, const secp256k1_gej *b) { + secp256k1_gej a2; + secp256k1_gej b2; + int ret = 1; + ret &= a->infinity == b->infinity; + if (ret && !a->infinity) { + a2 = *a; + b2 = *b; + secp256k1_fe_normalize(&a2.x); + secp256k1_fe_normalize(&a2.y); + secp256k1_fe_normalize(&a2.z); + secp256k1_fe_normalize(&b2.x); + secp256k1_fe_normalize(&b2.y); + secp256k1_fe_normalize(&b2.z); + ret &= secp256k1_fe_cmp_var(&a2.x, &b2.x) == 0; + ret &= secp256k1_fe_cmp_var(&a2.y, &b2.y) == 0; + ret &= secp256k1_fe_cmp_var(&a2.z, &b2.z) == 0; + } + return ret; +} + +void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { + secp256k1_fe z2s; + secp256k1_fe u1, u2, s1, s2; + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ + secp256k1_fe_sqr(&z2s, &b->z); + secp256k1_fe_mul(&u1, &a->x, &z2s); + u2 = b->x; secp256k1_fe_normalize_weak(&u2); + secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); + s2 = b->y; secp256k1_fe_normalize_weak(&s2); + CHECK(secp256k1_fe_equal_var(&u1, &u2)); + CHECK(secp256k1_fe_equal_var(&s1, &s2)); +} + +void test_ge(void) { + int i, i1; +#ifdef USE_ENDOMORPHISM + int runs = 6; +#else + int runs = 4; +#endif + /* Points: (infinity, p1, p1, -p1, -p1, p2, p2, -p2, -p2, p3, p3, -p3, -p3, p4, p4, -p4, -p4). + * The second in each pair of identical points uses a random Z coordinate in the Jacobian form. + * All magnitudes are randomized. + * All 17*17 combinations of points are added to each other, using all applicable methods. + * + * When the endomorphism code is compiled in, p5 = lambda*p1 and p6 = lambda^2*p1 are added as well. + */ + secp256k1_ge *ge = (secp256k1_ge *)malloc(sizeof(secp256k1_ge) * (1 + 4 * runs)); + secp256k1_gej *gej = (secp256k1_gej *)malloc(sizeof(secp256k1_gej) * (1 + 4 * runs)); + secp256k1_fe *zinv = (secp256k1_fe *)malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + secp256k1_fe zf; + secp256k1_fe zfi2, zfi3; + + secp256k1_gej_set_infinity(&gej[0]); + secp256k1_ge_clear(&ge[0]); + secp256k1_ge_set_gej_var(&ge[0], &gej[0]); + for (i = 0; i < runs; i++) { + int j; + secp256k1_ge g; + random_group_element_test(&g); +#ifdef USE_ENDOMORPHISM + if (i >= runs - 2) { + secp256k1_ge_mul_lambda(&g, &ge[1]); + } + if (i >= runs - 1) { + secp256k1_ge_mul_lambda(&g, &g); + } +#endif + ge[1 + 4 * i] = g; + ge[2 + 4 * i] = g; + secp256k1_ge_neg(&ge[3 + 4 * i], &g); + secp256k1_ge_neg(&ge[4 + 4 * i], &g); + secp256k1_gej_set_ge(&gej[1 + 4 * i], &ge[1 + 4 * i]); + random_group_element_jacobian_test(&gej[2 + 4 * i], &ge[2 + 4 * i]); + secp256k1_gej_set_ge(&gej[3 + 4 * i], &ge[3 + 4 * i]); + random_group_element_jacobian_test(&gej[4 + 4 * i], &ge[4 + 4 * i]); + for (j = 0; j < 4; j++) { + random_field_element_magnitude(&ge[1 + j + 4 * i].x); + random_field_element_magnitude(&ge[1 + j + 4 * i].y); + random_field_element_magnitude(&gej[1 + j + 4 * i].x); + random_field_element_magnitude(&gej[1 + j + 4 * i].y); + random_field_element_magnitude(&gej[1 + j + 4 * i].z); + } + } + + /* Compute z inverses. */ + { + secp256k1_fe *zs = malloc(sizeof(secp256k1_fe) * (1 + 4 * runs)); + for (i = 0; i < 4 * runs + 1; i++) { + if (i == 0) { + /* The point at infinity does not have a meaningful z inverse. Any should do. */ + do { + random_field_element_test(&zs[i]); + } while(secp256k1_fe_is_zero(&zs[i])); + } else { + zs[i] = gej[i].z; + } + } + secp256k1_fe_inv_all_var(zinv, zs, 4 * runs + 1); + free(zs); + } + + /* Generate random zf, and zfi2 = 1/zf^2, zfi3 = 1/zf^3 */ + do { + random_field_element_test(&zf); + } while(secp256k1_fe_is_zero(&zf)); + random_field_element_magnitude(&zf); + secp256k1_fe_inv_var(&zfi3, &zf); + secp256k1_fe_sqr(&zfi2, &zfi3); + secp256k1_fe_mul(&zfi3, &zfi3, &zfi2); + + for (i1 = 0; i1 < 1 + 4 * runs; i1++) { + int i2; + for (i2 = 0; i2 < 1 + 4 * runs; i2++) { + /* Compute reference result using gej + gej (var). */ + secp256k1_gej refj, resj; + secp256k1_ge ref; + secp256k1_fe zr; + secp256k1_gej_add_var(&refj, &gej[i1], &gej[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); + /* Check Z ratio. */ + if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&refj)) { + secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); + CHECK(secp256k1_fe_equal_var(&zrz, &refj.z)); + } + secp256k1_ge_set_gej_var(&ref, &refj); + + /* Test gej + ge with Z ratio result (var). */ + secp256k1_gej_add_ge_var(&resj, &gej[i1], &ge[i2], secp256k1_gej_is_infinity(&gej[i1]) ? NULL : &zr); + ge_equals_gej(&ref, &resj); + if (!secp256k1_gej_is_infinity(&gej[i1]) && !secp256k1_gej_is_infinity(&resj)) { + secp256k1_fe zrz; secp256k1_fe_mul(&zrz, &zr, &gej[i1].z); + CHECK(secp256k1_fe_equal_var(&zrz, &resj.z)); + } + + /* Test gej + ge (var, with additional Z factor). */ + { + secp256k1_ge ge2_zfi = ge[i2]; /* the second term with x and y rescaled for z = 1/zf */ + secp256k1_fe_mul(&ge2_zfi.x, &ge2_zfi.x, &zfi2); + secp256k1_fe_mul(&ge2_zfi.y, &ge2_zfi.y, &zfi3); + random_field_element_magnitude(&ge2_zfi.x); + random_field_element_magnitude(&ge2_zfi.y); + secp256k1_gej_add_zinv_var(&resj, &gej[i1], &ge2_zfi, &zf); + ge_equals_gej(&ref, &resj); + } + + /* Test gej + ge (const). */ + if (i2 != 0) { + /* secp256k1_gej_add_ge does not support its second argument being infinity. */ + secp256k1_gej_add_ge(&resj, &gej[i1], &ge[i2]); + ge_equals_gej(&ref, &resj); + } + + /* Test doubling (var). */ + if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 == ((i2 + 3)%4)/2)) { + secp256k1_fe zr2; + /* Normal doubling with Z ratio result. */ + secp256k1_gej_double_var(&resj, &gej[i1], &zr2); + ge_equals_gej(&ref, &resj); + /* Check Z ratio. */ + secp256k1_fe_mul(&zr2, &zr2, &gej[i1].z); + CHECK(secp256k1_fe_equal_var(&zr2, &resj.z)); + /* Normal doubling. */ + secp256k1_gej_double_var(&resj, &gej[i2], NULL); + ge_equals_gej(&ref, &resj); + } + + /* Test adding opposites. */ + if ((i1 == 0 && i2 == 0) || ((i1 + 3)/4 == (i2 + 3)/4 && ((i1 + 3)%4)/2 != ((i2 + 3)%4)/2)) { + CHECK(secp256k1_ge_is_infinity(&ref)); + } + + /* Test adding infinity. */ + if (i1 == 0) { + CHECK(secp256k1_ge_is_infinity(&ge[i1])); + CHECK(secp256k1_gej_is_infinity(&gej[i1])); + ge_equals_gej(&ref, &gej[i2]); + } + if (i2 == 0) { + CHECK(secp256k1_ge_is_infinity(&ge[i2])); + CHECK(secp256k1_gej_is_infinity(&gej[i2])); + ge_equals_gej(&ref, &gej[i1]); + } + } + } + + /* Test adding all points together in random order equals infinity. */ + { + secp256k1_gej sum = SECP256K1_GEJ_CONST_INFINITY; + secp256k1_gej *gej_shuffled = (secp256k1_gej *)malloc((4 * runs + 1) * sizeof(secp256k1_gej)); + for (i = 0; i < 4 * runs + 1; i++) { + gej_shuffled[i] = gej[i]; + } + for (i = 0; i < 4 * runs + 1; i++) { + int swap = i + secp256k1_rand_int(4 * runs + 1 - i); + if (swap != i) { + secp256k1_gej t = gej_shuffled[i]; + gej_shuffled[i] = gej_shuffled[swap]; + gej_shuffled[swap] = t; + } + } + for (i = 0; i < 4 * runs + 1; i++) { + secp256k1_gej_add_var(&sum, &sum, &gej_shuffled[i], NULL); + } + CHECK(secp256k1_gej_is_infinity(&sum)); + free(gej_shuffled); + } + + /* Test batch gej -> ge conversion with and without known z ratios. */ + { + secp256k1_fe *zr = (secp256k1_fe *)malloc((4 * runs + 1) * sizeof(secp256k1_fe)); + secp256k1_ge *ge_set_table = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); + secp256k1_ge *ge_set_all = (secp256k1_ge *)malloc((4 * runs + 1) * sizeof(secp256k1_ge)); + for (i = 0; i < 4 * runs + 1; i++) { + /* Compute gej[i + 1].z / gez[i].z (with gej[n].z taken to be 1). */ + if (i < 4 * runs) { + secp256k1_fe_mul(&zr[i + 1], &zinv[i], &gej[i + 1].z); + } + } + secp256k1_ge_set_table_gej_var(ge_set_table, gej, zr, 4 * runs + 1); + secp256k1_ge_set_all_gej_var(ge_set_all, gej, 4 * runs + 1, &ctx->error_callback); + for (i = 0; i < 4 * runs + 1; i++) { + secp256k1_fe s; + random_fe_non_zero(&s); + secp256k1_gej_rescale(&gej[i], &s); + ge_equals_gej(&ge_set_table[i], &gej[i]); + ge_equals_gej(&ge_set_all[i], &gej[i]); + } + free(ge_set_table); + free(ge_set_all); + free(zr); + } + + free(ge); + free(gej); + free(zinv); +} + +void test_add_neg_y_diff_x(void) { + /* The point of this test is to check that we can add two points + * whose y-coordinates are negatives of each other but whose x + * coordinates differ. If the x-coordinates were the same, these + * points would be negatives of each other and their sum is + * infinity. This is cool because it "covers up" any degeneracy + * in the addition algorithm that would cause the xy coordinates + * of the sum to be wrong (since infinity has no xy coordinates). + * HOWEVER, if the x-coordinates are different, infinity is the + * wrong answer, and such degeneracies are exposed. This is the + * root of https://github.com/bitcoin-core/secp256k1/issues/257 + * which this test is a regression test for. + * + * These points were generated in sage as + * # secp256k1 params + * F = FiniteField (0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F) + * C = EllipticCurve ([F (0), F (7)]) + * G = C.lift_x(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798) + * N = FiniteField(G.order()) + * + * # endomorphism values (lambda is 1^{1/3} in N, beta is 1^{1/3} in F) + * x = polygen(N) + * lam = (1 - x^3).roots()[1][0] + * + * # random "bad pair" + * P = C.random_element() + * Q = -int(lam) * P + * print " P: %x %x" % P.xy() + * print " Q: %x %x" % Q.xy() + * print "P + Q: %x %x" % (P + Q).xy() + */ + secp256k1_gej aj = SECP256K1_GEJ_CONST( + 0x8d24cd95, 0x0a355af1, 0x3c543505, 0x44238d30, + 0x0643d79f, 0x05a59614, 0x2f8ec030, 0xd58977cb, + 0x001e337a, 0x38093dcd, 0x6c0f386d, 0x0b1293a8, + 0x4d72c879, 0xd7681924, 0x44e6d2f3, 0x9190117d + ); + secp256k1_gej bj = SECP256K1_GEJ_CONST( + 0xc7b74206, 0x1f788cd9, 0xabd0937d, 0x164a0d86, + 0x95f6ff75, 0xf19a4ce9, 0xd013bd7b, 0xbf92d2a7, + 0xffe1cc85, 0xc7f6c232, 0x93f0c792, 0xf4ed6c57, + 0xb28d3786, 0x2897e6db, 0xbb192d0b, 0x6e6feab2 + ); + secp256k1_gej sumj = SECP256K1_GEJ_CONST( + 0x671a63c0, 0x3efdad4c, 0x389a7798, 0x24356027, + 0xb3d69010, 0x278625c3, 0x5c86d390, 0x184a8f7a, + 0x5f6409c2, 0x2ce01f2b, 0x511fd375, 0x25071d08, + 0xda651801, 0x70e95caf, 0x8f0d893c, 0xbed8fbbe + ); + secp256k1_ge b; + secp256k1_gej resj; + secp256k1_ge res; + secp256k1_ge_set_gej(&b, &bj); + + secp256k1_gej_add_var(&resj, &aj, &bj, NULL); + secp256k1_ge_set_gej(&res, &resj); + ge_equals_gej(&res, &sumj); + + secp256k1_gej_add_ge(&resj, &aj, &b); + secp256k1_ge_set_gej(&res, &resj); + ge_equals_gej(&res, &sumj); + + secp256k1_gej_add_ge_var(&resj, &aj, &b, NULL); + secp256k1_ge_set_gej(&res, &resj); + ge_equals_gej(&res, &sumj); +} + +void run_ge(void) { + int i; + for (i = 0; i < count * 32; i++) { + test_ge(); + } + test_add_neg_y_diff_x(); +} + +void test_ec_combine(void) { + secp256k1_scalar sum = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + secp256k1_pubkey data[6]; + const secp256k1_pubkey* d[6]; + secp256k1_pubkey sd; + secp256k1_pubkey sd2; + secp256k1_gej Qj; + secp256k1_ge Q; + int i; + for (i = 1; i <= 6; i++) { + secp256k1_scalar s; + random_scalar_order_test(&s); + secp256k1_scalar_add(&sum, &sum, &s); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &s); + secp256k1_ge_set_gej(&Q, &Qj); + secp256k1_pubkey_save(&data[i - 1], &Q); + d[i - 1] = &data[i - 1]; + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &Qj, &sum); + secp256k1_ge_set_gej(&Q, &Qj); + secp256k1_pubkey_save(&sd, &Q); + CHECK(secp256k1_ec_pubkey_combine(ctx, &sd2, d, i) == 1); + CHECK(memcmp(&sd, &sd2, sizeof(sd)) == 0); + } +} + +void run_ec_combine(void) { + int i; + for (i = 0; i < count * 8; i++) { + test_ec_combine(); + } +} + +void test_group_decompress(const secp256k1_fe* x) { + /* The input itself, normalized. */ + secp256k1_fe fex = *x; + secp256k1_fe fez; + /* Results of set_xquad_var, set_xo_var(..., 0), set_xo_var(..., 1). */ + secp256k1_ge ge_quad, ge_even, ge_odd; + secp256k1_gej gej_quad; + /* Return values of the above calls. */ + int res_quad, res_even, res_odd; + + secp256k1_fe_normalize_var(&fex); + + res_quad = secp256k1_ge_set_xquad(&ge_quad, &fex); + res_even = secp256k1_ge_set_xo_var(&ge_even, &fex, 0); + res_odd = secp256k1_ge_set_xo_var(&ge_odd, &fex, 1); + + CHECK(res_quad == res_even); + CHECK(res_quad == res_odd); + + if (res_quad) { + secp256k1_fe_normalize_var(&ge_quad.x); + secp256k1_fe_normalize_var(&ge_odd.x); + secp256k1_fe_normalize_var(&ge_even.x); + secp256k1_fe_normalize_var(&ge_quad.y); + secp256k1_fe_normalize_var(&ge_odd.y); + secp256k1_fe_normalize_var(&ge_even.y); + + /* No infinity allowed. */ + CHECK(!ge_quad.infinity); + CHECK(!ge_even.infinity); + CHECK(!ge_odd.infinity); + + /* Check that the x coordinates check out. */ + CHECK(secp256k1_fe_equal_var(&ge_quad.x, x)); + CHECK(secp256k1_fe_equal_var(&ge_even.x, x)); + CHECK(secp256k1_fe_equal_var(&ge_odd.x, x)); + + /* Check that the Y coordinate result in ge_quad is a square. */ + CHECK(secp256k1_fe_is_quad_var(&ge_quad.y)); + + /* Check odd/even Y in ge_odd, ge_even. */ + CHECK(secp256k1_fe_is_odd(&ge_odd.y)); + CHECK(!secp256k1_fe_is_odd(&ge_even.y)); + + /* Check secp256k1_gej_has_quad_y_var. */ + secp256k1_gej_set_ge(&gej_quad, &ge_quad); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); + do { + random_fe_test(&fez); + } while (secp256k1_fe_is_zero(&fez)); + secp256k1_gej_rescale(&gej_quad, &fez); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); + secp256k1_gej_neg(&gej_quad, &gej_quad); + CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); + do { + random_fe_test(&fez); + } while (secp256k1_fe_is_zero(&fez)); + secp256k1_gej_rescale(&gej_quad, &fez); + CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad)); + secp256k1_gej_neg(&gej_quad, &gej_quad); + CHECK(secp256k1_gej_has_quad_y_var(&gej_quad)); + } +} + +void run_group_decompress(void) { + int i; + for (i = 0; i < count * 4; i++) { + secp256k1_fe fe; + random_fe_test(&fe); + test_group_decompress(&fe); + } +} + +/***** ECMULT TESTS *****/ + +void run_ecmult_chain(void) { + /* random starting point A (on the curve) */ + secp256k1_gej a = SECP256K1_GEJ_CONST( + 0x8b30bbe9, 0xae2a9906, 0x96b22f67, 0x0709dff3, + 0x727fd8bc, 0x04d3362c, 0x6c7bf458, 0xe2846004, + 0xa357ae91, 0x5c4a6528, 0x1309edf2, 0x0504740f, + 0x0eb33439, 0x90216b4f, 0x81063cb6, 0x5f2f7e0f + ); + /* two random initial factors xn and gn */ + secp256k1_scalar xn = SECP256K1_SCALAR_CONST( + 0x84cc5452, 0xf7fde1ed, 0xb4d38a8c, 0xe9b1b84c, + 0xcef31f14, 0x6e569be9, 0x705d357a, 0x42985407 + ); + secp256k1_scalar gn = SECP256K1_SCALAR_CONST( + 0xa1e58d22, 0x553dcd42, 0xb2398062, 0x5d4c57a9, + 0x6e9323d4, 0x2b3152e5, 0xca2c3990, 0xedc7c9de + ); + /* two small multipliers to be applied to xn and gn in every iteration: */ + static const secp256k1_scalar xf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x1337); + static const secp256k1_scalar gf = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0x7113); + /* accumulators with the resulting coefficients to A and G */ + secp256k1_scalar ae = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_scalar ge = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + /* actual points */ + secp256k1_gej x; + secp256k1_gej x2; + int i; + + /* the point being computed */ + x = a; + for (i = 0; i < 200*count; i++) { + /* in each iteration, compute X = xn*X + gn*G; */ + secp256k1_ecmult(&ctx->ecmult_ctx, &x, &x, &xn, &gn); + /* also compute ae and ge: the actual accumulated factors for A and G */ + /* if X was (ae*A+ge*G), xn*X + gn*G results in (xn*ae*A + (xn*ge+gn)*G) */ + secp256k1_scalar_mul(&ae, &ae, &xn); + secp256k1_scalar_mul(&ge, &ge, &xn); + secp256k1_scalar_add(&ge, &ge, &gn); + /* modify xn and gn */ + secp256k1_scalar_mul(&xn, &xn, &xf); + secp256k1_scalar_mul(&gn, &gn, &gf); + + /* verify */ + if (i == 19999) { + /* expected result after 19999 iterations */ + secp256k1_gej rp = SECP256K1_GEJ_CONST( + 0xD6E96687, 0xF9B10D09, 0x2A6F3543, 0x9D86CEBE, + 0xA4535D0D, 0x409F5358, 0x6440BD74, 0xB933E830, + 0xB95CBCA2, 0xC77DA786, 0x539BE8FD, 0x53354D2D, + 0x3B4F566A, 0xE6580454, 0x07ED6015, 0xEE1B2A88 + ); + + secp256k1_gej_neg(&rp, &rp); + secp256k1_gej_add_var(&rp, &rp, &x, NULL); + CHECK(secp256k1_gej_is_infinity(&rp)); + } + } + /* redo the computation, but directly with the resulting ae and ge coefficients: */ + secp256k1_ecmult(&ctx->ecmult_ctx, &x2, &a, &ae, &ge); + secp256k1_gej_neg(&x2, &x2); + secp256k1_gej_add_var(&x2, &x2, &x, NULL); + CHECK(secp256k1_gej_is_infinity(&x2)); +} + +void test_point_times_order(const secp256k1_gej *point) { + /* X * (point + G) + (order-X) * (pointer + G) = 0 */ + secp256k1_scalar x; + secp256k1_scalar nx; + secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_gej res1, res2; + secp256k1_ge res3; + unsigned char pub[65]; + size_t psize = 65; + random_scalar_order_test(&x); + secp256k1_scalar_negate(&nx, &x); + secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &x, &x); /* calc res1 = x * point + x * G; */ + secp256k1_ecmult(&ctx->ecmult_ctx, &res2, point, &nx, &nx); /* calc res2 = (order - x) * point + (order - x) * G; */ + secp256k1_gej_add_var(&res1, &res1, &res2, NULL); + CHECK(secp256k1_gej_is_infinity(&res1)); + CHECK(secp256k1_gej_is_valid_var(&res1) == 0); + secp256k1_ge_set_gej(&res3, &res1); + CHECK(secp256k1_ge_is_infinity(&res3)); + CHECK(secp256k1_ge_is_valid_var(&res3) == 0); + CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 0) == 0); + psize = 65; + CHECK(secp256k1_eckey_pubkey_serialize(&res3, pub, &psize, 1) == 0); + /* check zero/one edge cases */ + secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &zero); + secp256k1_ge_set_gej(&res3, &res1); + CHECK(secp256k1_ge_is_infinity(&res3)); + secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &one, &zero); + secp256k1_ge_set_gej(&res3, &res1); + ge_equals_gej(&res3, point); + secp256k1_ecmult(&ctx->ecmult_ctx, &res1, point, &zero, &one); + secp256k1_ge_set_gej(&res3, &res1); + ge_equals_ge(&res3, &secp256k1_ge_const_g); +} + +void run_point_times_order(void) { + int i; + secp256k1_fe x = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 2); + static const secp256k1_fe xr = SECP256K1_FE_CONST( + 0x7603CB59, 0xB0EF6C63, 0xFE608479, 0x2A0C378C, + 0xDB3233A8, 0x0F8A9A09, 0xA877DEAD, 0x31B38C45 + ); + for (i = 0; i < 500; i++) { + secp256k1_ge p; + if (secp256k1_ge_set_xo_var(&p, &x, 1)) { + secp256k1_gej j; + CHECK(secp256k1_ge_is_valid_var(&p)); + secp256k1_gej_set_ge(&j, &p); + CHECK(secp256k1_gej_is_valid_var(&j)); + test_point_times_order(&j); + } + secp256k1_fe_sqr(&x, &x); + } + secp256k1_fe_normalize_var(&x); + CHECK(secp256k1_fe_equal_var(&x, &xr)); +} + +void ecmult_const_random_mult(void) { + /* random starting point A (on the curve) */ + secp256k1_ge a = SECP256K1_GE_CONST( + 0x6d986544, 0x57ff52b8, 0xcf1b8126, 0x5b802a5b, + 0xa97f9263, 0xb1e88044, 0x93351325, 0x91bc450a, + 0x535c59f7, 0x325e5d2b, 0xc391fbe8, 0x3c12787c, + 0x337e4a98, 0xe82a9011, 0x0123ba37, 0xdd769c7d + ); + /* random initial factor xn */ + secp256k1_scalar xn = SECP256K1_SCALAR_CONST( + 0x649d4f77, 0xc4242df7, 0x7f2079c9, 0x14530327, + 0xa31b876a, 0xd2d8ce2a, 0x2236d5c6, 0xd7b2029b + ); + /* expected xn * A (from sage) */ + secp256k1_ge expected_b = SECP256K1_GE_CONST( + 0x23773684, 0x4d209dc7, 0x098a786f, 0x20d06fcd, + 0x070a38bf, 0xc11ac651, 0x03004319, 0x1e2a8786, + 0xed8c3b8e, 0xc06dd57b, 0xd06ea66e, 0x45492b0f, + 0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956 + ); + secp256k1_gej b; + secp256k1_ecmult_const(&b, &a, &xn); + + CHECK(secp256k1_ge_is_valid_var(&a)); + ge_equals_gej(&expected_b, &b); +} + +void ecmult_const_commutativity(void) { + secp256k1_scalar a; + secp256k1_scalar b; + secp256k1_gej res1; + secp256k1_gej res2; + secp256k1_ge mid1; + secp256k1_ge mid2; + random_scalar_order_test(&a); + random_scalar_order_test(&b); + + secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a); + secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b); + secp256k1_ge_set_gej(&mid1, &res1); + secp256k1_ge_set_gej(&mid2, &res2); + secp256k1_ecmult_const(&res1, &mid1, &b); + secp256k1_ecmult_const(&res2, &mid2, &a); + secp256k1_ge_set_gej(&mid1, &res1); + secp256k1_ge_set_gej(&mid2, &res2); + ge_equals_ge(&mid1, &mid2); +} + +void ecmult_const_mult_zero_one(void) { + secp256k1_scalar zero = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 0); + secp256k1_scalar one = SECP256K1_SCALAR_CONST(0, 0, 0, 0, 0, 0, 0, 1); + secp256k1_scalar negone; + secp256k1_gej res1; + secp256k1_ge res2; + secp256k1_ge point; + secp256k1_scalar_negate(&negone, &one); + + random_group_element_test(&point); + secp256k1_ecmult_const(&res1, &point, &zero); + secp256k1_ge_set_gej(&res2, &res1); + CHECK(secp256k1_ge_is_infinity(&res2)); + secp256k1_ecmult_const(&res1, &point, &one); + secp256k1_ge_set_gej(&res2, &res1); + ge_equals_ge(&res2, &point); + secp256k1_ecmult_const(&res1, &point, &negone); + secp256k1_gej_neg(&res1, &res1); + secp256k1_ge_set_gej(&res2, &res1); + ge_equals_ge(&res2, &point); +} + +void ecmult_const_chain_multiply(void) { + /* Check known result (randomly generated test problem from sage) */ + const secp256k1_scalar scalar = SECP256K1_SCALAR_CONST( + 0x4968d524, 0x2abf9b7a, 0x466abbcf, 0x34b11b6d, + 0xcd83d307, 0x827bed62, 0x05fad0ce, 0x18fae63b + ); + const secp256k1_gej expected_point = SECP256K1_GEJ_CONST( + 0x5494c15d, 0x32099706, 0xc2395f94, 0x348745fd, + 0x757ce30e, 0x4e8c90fb, 0xa2bad184, 0xf883c69f, + 0x5d195d20, 0xe191bf7f, 0x1be3e55f, 0x56a80196, + 0x6071ad01, 0xf1462f66, 0xc997fa94, 0xdb858435 + ); + secp256k1_gej point; + secp256k1_ge res; + int i; + + secp256k1_gej_set_ge(&point, &secp256k1_ge_const_g); + for (i = 0; i < 100; ++i) { + secp256k1_ge tmp; + secp256k1_ge_set_gej(&tmp, &point); + secp256k1_ecmult_const(&point, &tmp, &scalar); + } + secp256k1_ge_set_gej(&res, &point); + ge_equals_gej(&res, &expected_point); +} + +void run_ecmult_const_tests(void) { + ecmult_const_mult_zero_one(); + ecmult_const_random_mult(); + ecmult_const_commutativity(); + ecmult_const_chain_multiply(); +} + +void test_wnaf(const secp256k1_scalar *number, int w) { + secp256k1_scalar x, two, t; + int wnaf[256]; + int zeroes = -1; + int i; + int bits; + secp256k1_scalar_set_int(&x, 0); + secp256k1_scalar_set_int(&two, 2); + bits = secp256k1_ecmult_wnaf(wnaf, 256, number, w); + CHECK(bits <= 256); + for (i = bits-1; i >= 0; i--) { + int v = wnaf[i]; + secp256k1_scalar_mul(&x, &x, &two); + if (v) { + CHECK(zeroes == -1 || zeroes >= w-1); /* check that distance between non-zero elements is at least w-1 */ + zeroes=0; + CHECK((v & 1) == 1); /* check non-zero elements are odd */ + CHECK(v <= (1 << (w-1)) - 1); /* check range below */ + CHECK(v >= -(1 << (w-1)) - 1); /* check range above */ + } else { + CHECK(zeroes != -1); /* check that no unnecessary zero padding exists */ + zeroes++; + } + if (v >= 0) { + secp256k1_scalar_set_int(&t, v); + } else { + secp256k1_scalar_set_int(&t, -v); + secp256k1_scalar_negate(&t, &t); + } + secp256k1_scalar_add(&x, &x, &t); + } + CHECK(secp256k1_scalar_eq(&x, number)); /* check that wnaf represents number */ +} + +void test_constant_wnaf_negate(const secp256k1_scalar *number) { + secp256k1_scalar neg1 = *number; + secp256k1_scalar neg2 = *number; + int sign1 = 1; + int sign2 = 1; + + if (!secp256k1_scalar_get_bits(&neg1, 0, 1)) { + secp256k1_scalar_negate(&neg1, &neg1); + sign1 = -1; + } + sign2 = secp256k1_scalar_cond_negate(&neg2, secp256k1_scalar_is_even(&neg2)); + CHECK(sign1 == sign2); + CHECK(secp256k1_scalar_eq(&neg1, &neg2)); +} + +void test_constant_wnaf(const secp256k1_scalar *number, int w) { + secp256k1_scalar x, shift; + int wnaf[256] = {0}; + int i; + int skew; + secp256k1_scalar num = *number; + + secp256k1_scalar_set_int(&x, 0); + secp256k1_scalar_set_int(&shift, 1 << w); + /* With USE_ENDOMORPHISM on we only consider 128-bit numbers */ +#ifdef USE_ENDOMORPHISM + for (i = 0; i < 16; ++i) { + secp256k1_scalar_shr_int(&num, 8); + } +#endif + skew = secp256k1_wnaf_const(wnaf, num, w); + + for (i = WNAF_SIZE(w); i >= 0; --i) { + secp256k1_scalar t; + int v = wnaf[i]; + CHECK(v != 0); /* check nonzero */ + CHECK(v & 1); /* check parity */ + CHECK(v > -(1 << w)); /* check range above */ + CHECK(v < (1 << w)); /* check range below */ + + secp256k1_scalar_mul(&x, &x, &shift); + if (v >= 0) { + secp256k1_scalar_set_int(&t, v); + } else { + secp256k1_scalar_set_int(&t, -v); + secp256k1_scalar_negate(&t, &t); + } + secp256k1_scalar_add(&x, &x, &t); + } + /* Skew num because when encoding numbers as odd we use an offset */ + secp256k1_scalar_cadd_bit(&num, skew == 2, 1); + CHECK(secp256k1_scalar_eq(&x, &num)); +} + +void run_wnaf(void) { + int i; + secp256k1_scalar n = {{0}}; + + /* Sanity check: 1 and 2 are the smallest odd and even numbers and should + * have easier-to-diagnose failure modes */ + n.d[0] = 1; + test_constant_wnaf(&n, 4); + n.d[0] = 2; + test_constant_wnaf(&n, 4); + /* Random tests */ + for (i = 0; i < count; i++) { + random_scalar_order(&n); + test_wnaf(&n, 4+(i%10)); + test_constant_wnaf_negate(&n); + test_constant_wnaf(&n, 4 + (i % 10)); + } + secp256k1_scalar_set_int(&n, 0); + CHECK(secp256k1_scalar_cond_negate(&n, 1) == -1); + CHECK(secp256k1_scalar_is_zero(&n)); + CHECK(secp256k1_scalar_cond_negate(&n, 0) == 1); + CHECK(secp256k1_scalar_is_zero(&n)); +} + +void test_ecmult_constants(void) { + /* Test ecmult_gen() for [0..36) and [order-36..0). */ + secp256k1_scalar x; + secp256k1_gej r; + secp256k1_ge ng; + int i; + int j; + secp256k1_ge_neg(&ng, &secp256k1_ge_const_g); + for (i = 0; i < 36; i++ ) { + secp256k1_scalar_set_int(&x, i); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); + for (j = 0; j < i; j++) { + if (j == i - 1) { + ge_equals_gej(&secp256k1_ge_const_g, &r); + } + secp256k1_gej_add_ge(&r, &r, &ng); + } + CHECK(secp256k1_gej_is_infinity(&r)); + } + for (i = 1; i <= 36; i++ ) { + secp256k1_scalar_set_int(&x, i); + secp256k1_scalar_negate(&x, &x); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &r, &x); + for (j = 0; j < i; j++) { + if (j == i - 1) { + ge_equals_gej(&ng, &r); + } + secp256k1_gej_add_ge(&r, &r, &secp256k1_ge_const_g); + } + CHECK(secp256k1_gej_is_infinity(&r)); + } +} + +void run_ecmult_constants(void) { + test_ecmult_constants(); +} + +void test_ecmult_gen_blind(void) { + /* Test ecmult_gen() blinding and confirm that the blinding changes, the affine points match, and the z's don't match. */ + secp256k1_scalar key; + secp256k1_scalar b; + unsigned char seed32[32]; + secp256k1_gej pgej; + secp256k1_gej pgej2; + secp256k1_gej i; + secp256k1_ge pge; + random_scalar_order_test(&key); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej, &key); + secp256k1_rand256(seed32); + b = ctx->ecmult_gen_ctx.blind; + i = ctx->ecmult_gen_ctx.initial; + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, seed32); + CHECK(!secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pgej2, &key); + CHECK(!gej_xyz_equals_gej(&pgej, &pgej2)); + CHECK(!gej_xyz_equals_gej(&i, &ctx->ecmult_gen_ctx.initial)); + secp256k1_ge_set_gej(&pge, &pgej); + ge_equals_gej(&pge, &pgej2); +} + +void test_ecmult_gen_blind_reset(void) { + /* Test ecmult_gen() blinding reset and confirm that the blinding is consistent. */ + secp256k1_scalar b; + secp256k1_gej initial; + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); + b = ctx->ecmult_gen_ctx.blind; + initial = ctx->ecmult_gen_ctx.initial; + secp256k1_ecmult_gen_blind(&ctx->ecmult_gen_ctx, 0); + CHECK(secp256k1_scalar_eq(&b, &ctx->ecmult_gen_ctx.blind)); + CHECK(gej_xyz_equals_gej(&initial, &ctx->ecmult_gen_ctx.initial)); +} + +void run_ecmult_gen_blind(void) { + int i; + test_ecmult_gen_blind_reset(); + for (i = 0; i < 10; i++) { + test_ecmult_gen_blind(); + } +} + +#ifdef USE_ENDOMORPHISM +/***** ENDOMORPHISH TESTS *****/ +void test_scalar_split(void) { + secp256k1_scalar full; + secp256k1_scalar s1, slam; + const unsigned char zero[32] = {0}; + unsigned char tmp[32]; + + random_scalar_order_test(&full); + secp256k1_scalar_split_lambda(&s1, &slam, &full); + + /* check that both are <= 128 bits in size */ + if (secp256k1_scalar_is_high(&s1)) { + secp256k1_scalar_negate(&s1, &s1); + } + if (secp256k1_scalar_is_high(&slam)) { + secp256k1_scalar_negate(&slam, &slam); + } + + secp256k1_scalar_get_b32(tmp, &s1); + CHECK(memcmp(zero, tmp, 16) == 0); + secp256k1_scalar_get_b32(tmp, &slam); + CHECK(memcmp(zero, tmp, 16) == 0); +} + +void run_endomorphism_tests(void) { + test_scalar_split(); +} +#endif + +void ec_pubkey_parse_pointtest(const unsigned char *input, int xvalid, int yvalid) { + unsigned char pubkeyc[65]; + secp256k1_pubkey pubkey; + secp256k1_ge ge; + size_t pubkeyclen; + int32_t ecount; + ecount = 0; + secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + for (pubkeyclen = 3; pubkeyclen <= 65; pubkeyclen++) { + /* Smaller sizes are tested exhaustively elsewhere. */ + int32_t i; + memcpy(&pubkeyc[1], input, 64); + VG_UNDEF(&pubkeyc[pubkeyclen], 65 - pubkeyclen); + for (i = 0; i < 256; i++) { + /* Try all type bytes. */ + int xpass; + int ypass; + int ysign; + pubkeyc[0] = i; + /* What sign does this point have? */ + ysign = (input[63] & 1) + 2; + /* For the current type (i) do we expect parsing to work? Handled all of compressed/uncompressed/hybrid. */ + xpass = xvalid && (pubkeyclen == 33) && ((i & 254) == 2); + /* Do we expect a parse and re-serialize as uncompressed to give a matching y? */ + ypass = xvalid && yvalid && ((i & 4) == ((pubkeyclen == 65) << 2)) && + ((i == 4) || ((i & 251) == ysign)) && ((pubkeyclen == 33) || (pubkeyclen == 65)); + if (xpass || ypass) { + /* These cases must parse. */ + unsigned char pubkeyo[65]; + size_t outl; + memset(&pubkey, 0, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + ecount = 0; + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + outl = 65; + VG_UNDEF(pubkeyo, 65); + CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + VG_CHECK(pubkeyo, outl); + CHECK(outl == 33); + CHECK(memcmp(&pubkeyo[1], &pubkeyc[1], 32) == 0); + CHECK((pubkeyclen != 33) || (pubkeyo[0] == pubkeyc[0])); + if (ypass) { + /* This test isn't always done because we decode with alternative signs, so the y won't match. */ + CHECK(pubkeyo[0] == ysign); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); + memset(&pubkey, 0, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + secp256k1_pubkey_save(&pubkey, &ge); + VG_CHECK(&pubkey, sizeof(pubkey)); + outl = 65; + VG_UNDEF(pubkeyo, 65); + CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyo, &outl, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); + VG_CHECK(pubkeyo, outl); + CHECK(outl == 65); + CHECK(pubkeyo[0] == 4); + CHECK(memcmp(&pubkeyo[1], input, 64) == 0); + } + CHECK(ecount == 0); + } else { + /* These cases must fail to parse. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + } + } + } + secp256k1_context_set_illegal_callback(ctx, NULL, NULL); +} + +void run_ec_pubkey_parse_test(void) { +#define SECP256K1_EC_PARSE_TEST_NVALID (12) + const unsigned char valid[SECP256K1_EC_PARSE_TEST_NVALID][64] = { + { + /* Point with leading and trailing zeros in x and y serialization. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x52, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x64, 0xef, 0xa1, 0x7b, 0x77, 0x61, 0xe1, 0xe4, 0x27, 0x06, 0x98, 0x9f, 0xb4, 0x83, + 0xb8, 0xd2, 0xd4, 0x9b, 0xf7, 0x8f, 0xae, 0x98, 0x03, 0xf0, 0x99, 0xb8, 0x34, 0xed, 0xeb, 0x00 + }, + { + /* Point with x equal to a 3rd root of unity.*/ + 0x7a, 0xe9, 0x6a, 0x2b, 0x65, 0x7c, 0x07, 0x10, 0x6e, 0x64, 0x47, 0x9e, 0xac, 0x34, 0x34, 0xe9, + 0x9c, 0xf0, 0x49, 0x75, 0x12, 0xf5, 0x89, 0x95, 0xc1, 0x39, 0x6c, 0x28, 0x71, 0x95, 0x01, 0xee, + 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, + 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, + }, + { + /* Point with largest x. (1/2) */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, + 0x0e, 0x99, 0x4b, 0x14, 0xea, 0x72, 0xf8, 0xc3, 0xeb, 0x95, 0xc7, 0x1e, 0xf6, 0x92, 0x57, 0x5e, + 0x77, 0x50, 0x58, 0x33, 0x2d, 0x7e, 0x52, 0xd0, 0x99, 0x5c, 0xf8, 0x03, 0x88, 0x71, 0xb6, 0x7d, + }, + { + /* Point with largest x. (2/2) */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2c, + 0xf1, 0x66, 0xb4, 0xeb, 0x15, 0x8d, 0x07, 0x3c, 0x14, 0x6a, 0x38, 0xe1, 0x09, 0x6d, 0xa8, 0xa1, + 0x88, 0xaf, 0xa7, 0xcc, 0xd2, 0x81, 0xad, 0x2f, 0x66, 0xa3, 0x07, 0xfb, 0x77, 0x8e, 0x45, 0xb2, + }, + { + /* Point with smallest x. (1/2) */ + 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, 0x01, + 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, + 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, + }, + { + /* Point with smallest x. (2/2) */ + 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, 0x01, + 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, + 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, + }, + { + /* Point with largest y. (1/3) */ + 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, + 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + }, + { + /* Point with largest y. (2/3) */ + 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, + 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + }, + { + /* Point with largest y. (3/3) */ + 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, + 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + }, + { + /* Point with smallest y. (1/3) */ + 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, + 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, + 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, 0x01, + }, + { + /* Point with smallest y. (2/3) */ + 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, + 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, + 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, 0x01, + }, + { + /* Point with smallest y. (3/3) */ + 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, + 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, + 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, 0x01 + } + }; +#define SECP256K1_EC_PARSE_TEST_NXVALID (4) + const unsigned char onlyxvalid[SECP256K1_EC_PARSE_TEST_NXVALID][64] = { + { + /* Valid if y overflow ignored (y = 1 mod p). (1/3) */ + 0x1f, 0xe1, 0xe5, 0xef, 0x3f, 0xce, 0xb5, 0xc1, 0x35, 0xab, 0x77, 0x41, 0x33, 0x3c, 0xe5, 0xa6, + 0xe8, 0x0d, 0x68, 0x16, 0x76, 0x53, 0xf6, 0xb2, 0xb2, 0x4b, 0xcb, 0xcf, 0xaa, 0xaf, 0xf5, 0x07, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + }, + { + /* Valid if y overflow ignored (y = 1 mod p). (2/3) */ + 0xcb, 0xb0, 0xde, 0xab, 0x12, 0x57, 0x54, 0xf1, 0xfd, 0xb2, 0x03, 0x8b, 0x04, 0x34, 0xed, 0x9c, + 0xb3, 0xfb, 0x53, 0xab, 0x73, 0x53, 0x91, 0x12, 0x99, 0x94, 0xa5, 0x35, 0xd9, 0x25, 0xf6, 0x73, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + }, + { + /* Valid if y overflow ignored (y = 1 mod p). (3/3)*/ + 0x14, 0x6d, 0x3b, 0x65, 0xad, 0xd9, 0xf5, 0x4c, 0xcc, 0xa2, 0x85, 0x33, 0xc8, 0x8e, 0x2c, 0xbc, + 0x63, 0xf7, 0x44, 0x3e, 0x16, 0x58, 0x78, 0x3a, 0xb4, 0x1f, 0x8e, 0xf9, 0x7c, 0x2a, 0x10, 0xb5, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + }, + { + /* x on curve, y is from y^2 = x^3 + 8. */ + 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, 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, 0x03 + } + }; +#define SECP256K1_EC_PARSE_TEST_NINVALID (7) + const unsigned char invalid[SECP256K1_EC_PARSE_TEST_NINVALID][64] = { + { + /* x is third root of -8, y is -1 * (x^3+7); also on the curve for y^2 = x^3 + 9. */ + 0x0a, 0x2d, 0x2b, 0xa9, 0x35, 0x07, 0xf1, 0xdf, 0x23, 0x37, 0x70, 0xc2, 0xa7, 0x97, 0x96, 0x2c, + 0xc6, 0x1f, 0x6d, 0x15, 0xda, 0x14, 0xec, 0xd4, 0x7d, 0x8d, 0x27, 0xae, 0x1c, 0xd5, 0xf8, 0x53, + 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, 0x01, + }, + { + /* Valid if x overflow ignored (x = 1 mod p). */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + 0x42, 0x18, 0xf2, 0x0a, 0xe6, 0xc6, 0x46, 0xb3, 0x63, 0xdb, 0x68, 0x60, 0x58, 0x22, 0xfb, 0x14, + 0x26, 0x4c, 0xa8, 0xd2, 0x58, 0x7f, 0xdd, 0x6f, 0xbc, 0x75, 0x0d, 0x58, 0x7e, 0x76, 0xa7, 0xee, + }, + { + /* Valid if x overflow ignored (x = 1 mod p). */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x30, + 0xbd, 0xe7, 0x0d, 0xf5, 0x19, 0x39, 0xb9, 0x4c, 0x9c, 0x24, 0x97, 0x9f, 0xa7, 0xdd, 0x04, 0xeb, + 0xd9, 0xb3, 0x57, 0x2d, 0xa7, 0x80, 0x22, 0x90, 0x43, 0x8a, 0xf2, 0xa6, 0x81, 0x89, 0x54, 0x41, + }, + { + /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + 0xf4, 0x84, 0x14, 0x5c, 0xb0, 0x14, 0x9b, 0x82, 0x5d, 0xff, 0x41, 0x2f, 0xa0, 0x52, 0xa8, 0x3f, + 0xcb, 0x72, 0xdb, 0x61, 0xd5, 0x6f, 0x37, 0x70, 0xce, 0x06, 0x6b, 0x73, 0x49, 0xa2, 0xaa, 0x28, + }, + { + /* x is -1, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 5. */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2e, + 0x0b, 0x7b, 0xeb, 0xa3, 0x4f, 0xeb, 0x64, 0x7d, 0xa2, 0x00, 0xbe, 0xd0, 0x5f, 0xad, 0x57, 0xc0, + 0x34, 0x8d, 0x24, 0x9e, 0x2a, 0x90, 0xc8, 0x8f, 0x31, 0xf9, 0x94, 0x8b, 0xb6, 0x5d, 0x52, 0x07, + }, + { + /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ + 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, + 0x8f, 0x53, 0x7e, 0xef, 0xdf, 0xc1, 0x60, 0x6a, 0x07, 0x27, 0xcd, 0x69, 0xb4, 0xa7, 0x33, 0x3d, + 0x38, 0xed, 0x44, 0xe3, 0x93, 0x2a, 0x71, 0x79, 0xee, 0xcb, 0x4b, 0x6f, 0xba, 0x93, 0x60, 0xdc, + }, + { + /* x is zero, y is the result of the sqrt ladder; also on the curve for y^2 = x^3 - 7. */ + 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, + 0x70, 0xac, 0x81, 0x10, 0x20, 0x3e, 0x9f, 0x95, 0xf8, 0xd8, 0x32, 0x96, 0x4b, 0x58, 0xcc, 0xc2, + 0xc7, 0x12, 0xbb, 0x1c, 0x6c, 0xd5, 0x8e, 0x86, 0x11, 0x34, 0xb4, 0x8f, 0x45, 0x6c, 0x9b, 0x53 + } + }; + const unsigned char pubkeyc[66] = { + /* Serialization of G. */ + 0x04, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, + 0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, + 0x98, 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, + 0xA8, 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, + 0xB8, 0x00 + }; + unsigned char sout[65]; + unsigned char shortkey[2]; + secp256k1_ge ge; + secp256k1_pubkey pubkey; + size_t len; + int32_t i; + int32_t ecount; + int32_t ecount2; + ecount = 0; + /* Nothing should be reading this far into pubkeyc. */ + VG_UNDEF(&pubkeyc[65], 1); + secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + /* Zero length claimed, fail, zeroize, no illegal arg error. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(shortkey, 2); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 0) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + /* Length one claimed, fail, zeroize, no illegal arg error. */ + for (i = 0; i < 256 ; i++) { + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + shortkey[0] = i; + VG_UNDEF(&shortkey[1], 1); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 1) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + } + /* Length two claimed, fail, zeroize, no illegal arg error. */ + for (i = 0; i < 65536 ; i++) { + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + shortkey[0] = i & 255; + shortkey[1] = i >> 8; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, shortkey, 2) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + } + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + /* 33 bytes claimed on otherwise valid input starting with 0x04, fail, zeroize output, no illegal arg error. */ + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 33) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + /* NULL pubkey, illegal arg error. Pubkey isn't rewritten before this step, since it's NULL into the parser. */ + CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, pubkeyc, 65) == 0); + CHECK(ecount == 2); + /* NULL input string. Illegal arg and zeroize output. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, NULL, 65) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 1); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 2); + /* 64 bytes claimed on input starting with 0x04, fail, zeroize output, no illegal arg error. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 64) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + /* 66 bytes claimed, fail, zeroize output, no illegal arg error. */ + memset(&pubkey, 0xfe, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 66) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 0); + CHECK(ecount == 1); + /* Valid parse. */ + memset(&pubkey, 0, sizeof(pubkey)); + ecount = 0; + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, 65) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(ecount == 0); + VG_UNDEF(&ge, sizeof(ge)); + CHECK(secp256k1_pubkey_load(ctx, &ge, &pubkey) == 1); + VG_CHECK(&ge.x, sizeof(ge.x)); + VG_CHECK(&ge.y, sizeof(ge.y)); + VG_CHECK(&ge.infinity, sizeof(ge.infinity)); + ge_equals_ge(&secp256k1_ge_const_g, &ge); + CHECK(ecount == 0); + /* secp256k1_ec_pubkey_serialize illegal args. */ + ecount = 0; + len = 65; + CHECK(secp256k1_ec_pubkey_serialize(ctx, NULL, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); + CHECK(ecount == 1); + CHECK(len == 0); + CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, NULL, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 0); + CHECK(ecount == 2); + len = 65; + VG_UNDEF(sout, 65); + CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, NULL, SECP256K1_EC_UNCOMPRESSED) == 0); + VG_CHECK(sout, 65); + CHECK(ecount == 3); + CHECK(len == 0); + len = 65; + CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, ~0) == 0); + CHECK(ecount == 4); + CHECK(len == 0); + len = 65; + VG_UNDEF(sout, 65); + CHECK(secp256k1_ec_pubkey_serialize(ctx, sout, &len, &pubkey, SECP256K1_EC_UNCOMPRESSED) == 1); + VG_CHECK(sout, 65); + CHECK(ecount == 4); + CHECK(len == 65); + /* Multiple illegal args. Should still set arg error only once. */ + ecount = 0; + ecount2 = 11; + CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); + CHECK(ecount == 1); + /* Does the illegal arg callback actually change the behavior? */ + secp256k1_context_set_illegal_callback(ctx, uncounting_illegal_callback_fn, &ecount2); + CHECK(secp256k1_ec_pubkey_parse(ctx, NULL, NULL, 65) == 0); + CHECK(ecount == 1); + CHECK(ecount2 == 10); + secp256k1_context_set_illegal_callback(ctx, NULL, NULL); + /* Try a bunch of prefabbed points with all possible encodings. */ + for (i = 0; i < SECP256K1_EC_PARSE_TEST_NVALID; i++) { + ec_pubkey_parse_pointtest(valid[i], 1, 1); + } + for (i = 0; i < SECP256K1_EC_PARSE_TEST_NXVALID; i++) { + ec_pubkey_parse_pointtest(onlyxvalid[i], 1, 0); + } + for (i = 0; i < SECP256K1_EC_PARSE_TEST_NINVALID; i++) { + ec_pubkey_parse_pointtest(invalid[i], 0, 0); + } +} + +void run_eckey_edge_case_test(void) { + const unsigned char orderc[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41 + }; + const unsigned char zeros[sizeof(secp256k1_pubkey)] = {0x00}; + unsigned char ctmp[33]; + unsigned char ctmp2[33]; + secp256k1_pubkey pubkey; + secp256k1_pubkey pubkey2; + secp256k1_pubkey pubkey_one; + secp256k1_pubkey pubkey_negone; + const secp256k1_pubkey *pubkeys[3]; + size_t len; + int32_t ecount; + /* Group order is too large, reject. */ + CHECK(secp256k1_ec_seckey_verify(ctx, orderc) == 0); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, orderc) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* Maximum value is too large, reject. */ + memset(ctmp, 255, 32); + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); + memset(&pubkey, 1, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* Zero is too small, reject. */ + memset(ctmp, 0, 32); + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); + memset(&pubkey, 1, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* One must be accepted. */ + ctmp[31] = 0x01; + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + memset(&pubkey, 0, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + pubkey_one = pubkey; + /* Group order + 1 is too large, reject. */ + memcpy(ctmp, orderc, 32); + ctmp[31] = 0x42; + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 0); + memset(&pubkey, 1, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 0); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* -1 must be accepted. */ + ctmp[31] = 0x40; + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + memset(&pubkey, 0, sizeof(pubkey)); + VG_UNDEF(&pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, ctmp) == 1); + VG_CHECK(&pubkey, sizeof(pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + pubkey_negone = pubkey; + /* Tweak of zero leaves the value changed. */ + memset(ctmp2, 0, 32); + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, ctmp2) == 1); + CHECK(memcmp(orderc, ctmp, 31) == 0 && ctmp[31] == 0x40); + memcpy(&pubkey2, &pubkey, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + /* Multiply tweak of zero zeroizes the output. */ + CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, ctmp2) == 0); + CHECK(memcmp(zeros, ctmp, 32) == 0); + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, ctmp2) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + /* Overflowing key tweak zeroizes. */ + memcpy(ctmp, orderc, 32); + ctmp[31] = 0x40; + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, orderc) == 0); + CHECK(memcmp(zeros, ctmp, 32) == 0); + memcpy(ctmp, orderc, 32); + ctmp[31] = 0x40; + CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, orderc) == 0); + CHECK(memcmp(zeros, ctmp, 32) == 0); + memcpy(ctmp, orderc, 32); + ctmp[31] = 0x40; + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, orderc) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, orderc) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + /* Private key tweaks results in a key of zero. */ + ctmp2[31] = 1; + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 0); + CHECK(memcmp(zeros, ctmp2, 32) == 0); + ctmp2[31] = 1; + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + /* Tweak computation wraps and results in a key of 1. */ + ctmp2[31] = 2; + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp2, ctmp) == 1); + CHECK(memcmp(ctmp2, zeros, 31) == 0 && ctmp2[31] == 1); + ctmp2[31] = 2; + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + ctmp2[31] = 1; + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, ctmp2) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + /* Tweak mul * 2 = 1+1. */ + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 1); + ctmp2[31] = 2; + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + /* Test argument errors. */ + ecount = 0; + secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + CHECK(ecount == 0); + /* Zeroize pubkey on parse error. */ + memset(&pubkey, 0, 32); + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(memcmp(&pubkey, zeros, sizeof(pubkey)) == 0); + memcpy(&pubkey, &pubkey2, sizeof(pubkey)); + memset(&pubkey2, 0, 32); + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey2, ctmp2) == 0); + CHECK(ecount == 2); + CHECK(memcmp(&pubkey2, zeros, sizeof(pubkey2)) == 0); + /* Plain argument errors. */ + ecount = 0; + CHECK(secp256k1_ec_seckey_verify(ctx, ctmp) == 1); + CHECK(ecount == 0); + CHECK(secp256k1_ec_seckey_verify(ctx, NULL) == 0); + CHECK(ecount == 1); + ecount = 0; + memset(ctmp2, 0, 32); + ctmp2[31] = 4; + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, NULL, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, NULL) == 0); + CHECK(ecount == 2); + ecount = 0; + memset(ctmp2, 0, 32); + ctmp2[31] = 4; + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, NULL, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, NULL) == 0); + CHECK(ecount == 2); + ecount = 0; + memset(ctmp2, 0, 32); + CHECK(secp256k1_ec_privkey_tweak_add(ctx, NULL, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_privkey_tweak_add(ctx, ctmp, NULL) == 0); + CHECK(ecount == 2); + ecount = 0; + memset(ctmp2, 0, 32); + ctmp2[31] = 1; + CHECK(secp256k1_ec_privkey_tweak_mul(ctx, NULL, ctmp2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_privkey_tweak_mul(ctx, ctmp, NULL) == 0); + CHECK(ecount == 2); + ecount = 0; + CHECK(secp256k1_ec_pubkey_create(ctx, NULL, ctmp) == 0); + CHECK(ecount == 1); + memset(&pubkey, 1, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); + CHECK(ecount == 2); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + /* secp256k1_ec_pubkey_combine tests. */ + ecount = 0; + pubkeys[0] = &pubkey_one; + VG_UNDEF(&pubkeys[0], sizeof(secp256k1_pubkey *)); + VG_UNDEF(&pubkeys[1], sizeof(secp256k1_pubkey *)); + VG_UNDEF(&pubkeys[2], sizeof(secp256k1_pubkey *)); + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 0) == 0); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ec_pubkey_combine(ctx, NULL, pubkeys, 1) == 0); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(ecount == 2); + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, NULL, 1) == 0); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(ecount == 3); + pubkeys[0] = &pubkey_negone; + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 1) == 1); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + CHECK(ecount == 3); + len = 33; + CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_negone, SECP256K1_EC_COMPRESSED) == 1); + CHECK(memcmp(ctmp, ctmp2, 33) == 0); + /* Result is infinity. */ + pubkeys[0] = &pubkey_one; + pubkeys[1] = &pubkey_negone; + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 0); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) == 0); + CHECK(ecount == 3); + /* Passes through infinity but comes out one. */ + pubkeys[2] = &pubkey_one; + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 3) == 1); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + CHECK(ecount == 3); + len = 33; + CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp, &len, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + CHECK(secp256k1_ec_pubkey_serialize(ctx, ctmp2, &len, &pubkey_one, SECP256K1_EC_COMPRESSED) == 1); + CHECK(memcmp(ctmp, ctmp2, 33) == 0); + /* Adds to two. */ + pubkeys[1] = &pubkey_one; + memset(&pubkey, 255, sizeof(secp256k1_pubkey)); + VG_UNDEF(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(secp256k1_ec_pubkey_combine(ctx, &pubkey, pubkeys, 2) == 1); + VG_CHECK(&pubkey, sizeof(secp256k1_pubkey)); + CHECK(memcmp(&pubkey, zeros, sizeof(secp256k1_pubkey)) > 0); + CHECK(ecount == 3); + secp256k1_context_set_illegal_callback(ctx, NULL, NULL); +} + +void random_sign(secp256k1_scalar *sigr, secp256k1_scalar *sigs, const secp256k1_scalar *key, const secp256k1_scalar *msg, int *recid) { + secp256k1_scalar nonce; + do { + random_scalar_order_test(&nonce); + } while(!secp256k1_ecdsa_sig_sign(&ctx->ecmult_gen_ctx, sigr, sigs, key, msg, &nonce, recid)); +} + +void test_ecdsa_sign_verify(void) { + secp256k1_gej pubj; + secp256k1_ge pub; + secp256k1_scalar one; + secp256k1_scalar msg, key; + secp256k1_scalar sigr, sigs; + int recid; + int getrec; + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pubj, &key); + secp256k1_ge_set_gej(&pub, &pubj); + getrec = secp256k1_rand_bits(1); + random_sign(&sigr, &sigs, &key, &msg, getrec?&recid:NULL); + if (getrec) { + CHECK(recid >= 0 && recid < 4); + } + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); + secp256k1_scalar_set_int(&one, 1); + secp256k1_scalar_add(&msg, &msg, &one); + CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &pub, &msg)); +} + +void run_ecdsa_sign_verify(void) { + int i; + for (i = 0; i < 10*count; i++) { + test_ecdsa_sign_verify(); + } +} + +/** Dummy nonce generation function that just uses a precomputed nonce, and fails if it is not accepted. Use only for testing. */ +static int precomputed_nonce_function(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + (void)msg32; + (void)key32; + (void)algo16; + memcpy(nonce32, data, 32); + return (counter == 0); +} + +static int nonce_function_test_fail(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + /* Dummy nonce generator that has a fatal error on the first counter value. */ + if (counter == 0) { + return 0; + } + return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 1); +} + +static int nonce_function_test_retry(unsigned char *nonce32, const unsigned char *msg32, const unsigned char *key32, const unsigned char *algo16, void *data, unsigned int counter) { + /* Dummy nonce generator that produces unacceptable nonces for the first several counter values. */ + if (counter < 3) { + memset(nonce32, counter==0 ? 0 : 255, 32); + if (counter == 2) { + nonce32[31]--; + } + return 1; + } + if (counter < 5) { + static const unsigned char order[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x41 + }; + memcpy(nonce32, order, 32); + if (counter == 4) { + nonce32[31]++; + } + return 1; + } + /* Retry rate of 6979 is negligible esp. as we only call this in deterministic tests. */ + /* If someone does fine a case where it retries for secp256k1, we'd like to know. */ + if (counter > 5) { + return 0; + } + return nonce_function_rfc6979(nonce32, msg32, key32, algo16, data, counter - 5); +} + +int is_empty_signature(const secp256k1_ecdsa_signature *sig) { + static const unsigned char res[sizeof(secp256k1_ecdsa_signature)] = {0}; + return memcmp(sig, res, sizeof(secp256k1_ecdsa_signature)) == 0; +} + +void test_ecdsa_end_to_end(void) { + unsigned char extra[32] = {0x00}; + unsigned char privkey[32]; + unsigned char message[32]; + unsigned char privkey2[32]; + secp256k1_ecdsa_signature signature[6]; + secp256k1_scalar r, s; + unsigned char sig[74]; + size_t siglen = 74; + unsigned char pubkeyc[65]; + size_t pubkeyclen = 65; + secp256k1_pubkey pubkey; + unsigned char seckey[300]; + size_t seckeylen = 300; + + /* Generate a random key and message. */ + { + secp256k1_scalar msg, key; + random_scalar_order_test(&msg); + random_scalar_order_test(&key); + secp256k1_scalar_get_b32(privkey, &key); + secp256k1_scalar_get_b32(message, &msg); + } + + /* Construct and verify corresponding public key. */ + CHECK(secp256k1_ec_seckey_verify(ctx, privkey) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, privkey) == 1); + + /* Verify exporting and importing public key. */ + CHECK(secp256k1_ec_pubkey_serialize(ctx, pubkeyc, &pubkeyclen, &pubkey, secp256k1_rand_bits(1) == 1 ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED)); + memset(&pubkey, 0, sizeof(pubkey)); + CHECK(secp256k1_ec_pubkey_parse(ctx, &pubkey, pubkeyc, pubkeyclen) == 1); + + /* Verify private key import and export. */ + CHECK(ec_privkey_export_der(ctx, seckey, &seckeylen, privkey, secp256k1_rand_bits(1) == 1)); + CHECK(ec_privkey_import_der(ctx, privkey2, seckey, seckeylen) == 1); + CHECK(memcmp(privkey, privkey2, 32) == 0); + + /* Optionally tweak the keys using addition. */ + if (secp256k1_rand_int(3) == 0) { + int ret1; + int ret2; + unsigned char rnd[32]; + secp256k1_pubkey pubkey2; + secp256k1_rand256_test(rnd); + ret1 = secp256k1_ec_privkey_tweak_add(ctx, privkey, rnd); + ret2 = secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, rnd); + CHECK(ret1 == ret2); + if (ret1 == 0) { + return; + } + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + } + + /* Optionally tweak the keys using multiplication. */ + if (secp256k1_rand_int(3) == 0) { + int ret1; + int ret2; + unsigned char rnd[32]; + secp256k1_pubkey pubkey2; + secp256k1_rand256_test(rnd); + ret1 = secp256k1_ec_privkey_tweak_mul(ctx, privkey, rnd); + ret2 = secp256k1_ec_pubkey_tweak_mul(ctx, &pubkey, rnd); + CHECK(ret1 == ret2); + if (ret1 == 0) { + return; + } + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey2, privkey) == 1); + CHECK(memcmp(&pubkey, &pubkey2, sizeof(pubkey)) == 0); + } + + /* Sign. */ + CHECK(secp256k1_ecdsa_sign(ctx, &signature[0], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, &signature[4], message, privkey, NULL, NULL) == 1); + CHECK(secp256k1_ecdsa_sign(ctx, &signature[1], message, privkey, NULL, extra) == 1); + extra[31] = 1; + CHECK(secp256k1_ecdsa_sign(ctx, &signature[2], message, privkey, NULL, extra) == 1); + extra[31] = 0; + extra[0] = 1; + CHECK(secp256k1_ecdsa_sign(ctx, &signature[3], message, privkey, NULL, extra) == 1); + CHECK(memcmp(&signature[0], &signature[4], sizeof(signature[0])) == 0); + CHECK(memcmp(&signature[0], &signature[1], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[0], &signature[2], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[0], &signature[3], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[1], &signature[2], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[1], &signature[3], sizeof(signature[0])) != 0); + CHECK(memcmp(&signature[2], &signature[3], sizeof(signature[0])) != 0); + /* Verify. */ + CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[1], message, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[2], message, &pubkey) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[3], message, &pubkey) == 1); + /* Test lower-S form, malleate, verify and fail, test again, malleate again */ + CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[0])); + secp256k1_ecdsa_signature_load(ctx, &r, &s, &signature[0]); + secp256k1_scalar_negate(&s, &s); + secp256k1_ecdsa_signature_save(&signature[5], &r, &s); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 0); + CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); + CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(!secp256k1_ecdsa_signature_normalize(ctx, &signature[5], &signature[5])); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); + secp256k1_scalar_negate(&s, &s); + secp256k1_ecdsa_signature_save(&signature[5], &r, &s); + CHECK(!secp256k1_ecdsa_signature_normalize(ctx, NULL, &signature[5])); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[5], message, &pubkey) == 1); + CHECK(memcmp(&signature[5], &signature[0], 64) == 0); + + /* Serialize/parse DER and verify again */ + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); + memset(&signature[0], 0, sizeof(signature[0])); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 1); + /* Serialize/destroy/parse DER and verify again. */ + siglen = 74; + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, sig, &siglen, &signature[0]) == 1); + sig[secp256k1_rand_int(siglen)] += 1 + secp256k1_rand_int(255); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &signature[0], sig, siglen) == 0 || + secp256k1_ecdsa_verify(ctx, &signature[0], message, &pubkey) == 0); +} + +void test_random_pubkeys(void) { + secp256k1_ge elem; + secp256k1_ge elem2; + unsigned char in[65]; + /* Generate some randomly sized pubkeys. */ + size_t len = secp256k1_rand_bits(2) == 0 ? 65 : 33; + if (secp256k1_rand_bits(2) == 0) { + len = secp256k1_rand_bits(6); + } + if (len == 65) { + in[0] = secp256k1_rand_bits(1) ? 4 : (secp256k1_rand_bits(1) ? 6 : 7); + } else { + in[0] = secp256k1_rand_bits(1) ? 2 : 3; + } + if (secp256k1_rand_bits(3) == 0) { + in[0] = secp256k1_rand_bits(8); + } + if (len > 1) { + secp256k1_rand256(&in[1]); + } + if (len > 33) { + secp256k1_rand256(&in[33]); + } + if (secp256k1_eckey_pubkey_parse(&elem, in, len)) { + unsigned char out[65]; + unsigned char firstb; + int res; + size_t size = len; + firstb = in[0]; + /* If the pubkey can be parsed, it should round-trip... */ + CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, len == 33)); + CHECK(size == len); + CHECK(memcmp(&in[1], &out[1], len-1) == 0); + /* ... except for the type of hybrid inputs. */ + if ((in[0] != 6) && (in[0] != 7)) { + CHECK(in[0] == out[0]); + } + size = 65; + CHECK(secp256k1_eckey_pubkey_serialize(&elem, in, &size, 0)); + CHECK(size == 65); + CHECK(secp256k1_eckey_pubkey_parse(&elem2, in, size)); + ge_equals_ge(&elem,&elem2); + /* Check that the X9.62 hybrid type is checked. */ + in[0] = secp256k1_rand_bits(1) ? 6 : 7; + res = secp256k1_eckey_pubkey_parse(&elem2, in, size); + if (firstb == 2 || firstb == 3) { + if (in[0] == firstb + 4) { + CHECK(res); + } else { + CHECK(!res); + } + } + if (res) { + ge_equals_ge(&elem,&elem2); + CHECK(secp256k1_eckey_pubkey_serialize(&elem, out, &size, 0)); + CHECK(memcmp(&in[1], &out[1], 64) == 0); + } + } +} + +void run_random_pubkeys(void) { + int i; + for (i = 0; i < 10*count; i++) { + test_random_pubkeys(); + } +} + +void run_ecdsa_end_to_end(void) { + int i; + for (i = 0; i < 64*count; i++) { + test_ecdsa_end_to_end(); + } +} + +int test_ecdsa_der_parse(const unsigned char *sig, size_t siglen, int certainly_der, int certainly_not_der) { + static const unsigned char zeroes[32] = {0}; +#ifdef ENABLE_OPENSSL_TESTS + static const unsigned char max_scalar[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x40 + }; +#endif + + int ret = 0; + + secp256k1_ecdsa_signature sig_der; + unsigned char roundtrip_der[2048]; + unsigned char compact_der[64]; + size_t len_der = 2048; + int parsed_der = 0, valid_der = 0, roundtrips_der = 0; + + secp256k1_ecdsa_signature sig_der_lax; + unsigned char roundtrip_der_lax[2048]; + unsigned char compact_der_lax[64]; + size_t len_der_lax = 2048; + int parsed_der_lax = 0, valid_der_lax = 0, roundtrips_der_lax = 0; + +#ifdef ENABLE_OPENSSL_TESTS + ECDSA_SIG *sig_openssl; + const unsigned char *sigptr; + unsigned char roundtrip_openssl[2048]; + int len_openssl = 2048; + int parsed_openssl, valid_openssl = 0, roundtrips_openssl = 0; +#endif + + parsed_der = secp256k1_ecdsa_signature_parse_der(ctx, &sig_der, sig, siglen); + if (parsed_der) { + ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der, &sig_der)) << 0; + valid_der = (memcmp(compact_der, zeroes, 32) != 0) && (memcmp(compact_der + 32, zeroes, 32) != 0); + } + if (valid_der) { + ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der, &len_der, &sig_der)) << 1; + roundtrips_der = (len_der == siglen) && memcmp(roundtrip_der, sig, siglen) == 0; + } + + parsed_der_lax = ecdsa_signature_parse_der_lax(ctx, &sig_der_lax, sig, siglen); + if (parsed_der_lax) { + ret |= (!secp256k1_ecdsa_signature_serialize_compact(ctx, compact_der_lax, &sig_der_lax)) << 10; + valid_der_lax = (memcmp(compact_der_lax, zeroes, 32) != 0) && (memcmp(compact_der_lax + 32, zeroes, 32) != 0); + } + if (valid_der_lax) { + ret |= (!secp256k1_ecdsa_signature_serialize_der(ctx, roundtrip_der_lax, &len_der_lax, &sig_der_lax)) << 11; + roundtrips_der_lax = (len_der_lax == siglen) && memcmp(roundtrip_der_lax, sig, siglen) == 0; + } + + if (certainly_der) { + ret |= (!parsed_der) << 2; + } + if (certainly_not_der) { + ret |= (parsed_der) << 17; + } + if (valid_der) { + ret |= (!roundtrips_der) << 3; + } + + if (valid_der) { + ret |= (!roundtrips_der_lax) << 12; + ret |= (len_der != len_der_lax) << 13; + ret |= (memcmp(roundtrip_der_lax, roundtrip_der, len_der) != 0) << 14; + } + ret |= (roundtrips_der != roundtrips_der_lax) << 15; + if (parsed_der) { + ret |= (!parsed_der_lax) << 16; + } + +#ifdef ENABLE_OPENSSL_TESTS + sig_openssl = ECDSA_SIG_new(); + sigptr = sig; + parsed_openssl = (d2i_ECDSA_SIG(&sig_openssl, &sigptr, siglen) != NULL); + if (parsed_openssl) { + valid_openssl = !BN_is_negative(sig_openssl->r) && !BN_is_negative(sig_openssl->s) && BN_num_bits(sig_openssl->r) > 0 && BN_num_bits(sig_openssl->r) <= 256 && BN_num_bits(sig_openssl->s) > 0 && BN_num_bits(sig_openssl->s) <= 256; + if (valid_openssl) { + unsigned char tmp[32] = {0}; + BN_bn2bin(sig_openssl->r, tmp + 32 - BN_num_bytes(sig_openssl->r)); + valid_openssl = memcmp(tmp, max_scalar, 32) < 0; + } + if (valid_openssl) { + unsigned char tmp[32] = {0}; + BN_bn2bin(sig_openssl->s, tmp + 32 - BN_num_bytes(sig_openssl->s)); + valid_openssl = memcmp(tmp, max_scalar, 32) < 0; + } + } + len_openssl = i2d_ECDSA_SIG(sig_openssl, NULL); + if (len_openssl <= 2048) { + unsigned char *ptr = roundtrip_openssl; + CHECK(i2d_ECDSA_SIG(sig_openssl, &ptr) == len_openssl); + roundtrips_openssl = valid_openssl && ((size_t)len_openssl == siglen) && (memcmp(roundtrip_openssl, sig, siglen) == 0); + } else { + len_openssl = 0; + } + ECDSA_SIG_free(sig_openssl); + + ret |= (parsed_der && !parsed_openssl) << 4; + ret |= (valid_der && !valid_openssl) << 5; + ret |= (roundtrips_openssl && !parsed_der) << 6; + ret |= (roundtrips_der != roundtrips_openssl) << 7; + if (roundtrips_openssl) { + ret |= (len_der != (size_t)len_openssl) << 8; + ret |= (memcmp(roundtrip_der, roundtrip_openssl, len_der) != 0) << 9; + } +#endif + return ret; +} + +static void assign_big_endian(unsigned char *ptr, size_t ptrlen, uint32_t val) { + size_t i; + for (i = 0; i < ptrlen; i++) { + int shift = ptrlen - 1 - i; + if (shift >= 4) { + ptr[i] = 0; + } else { + ptr[i] = (val >> shift) & 0xFF; + } + } +} + +static void damage_array(unsigned char *sig, size_t *len) { + int pos; + int action = secp256k1_rand_bits(3); + if (action < 1 && *len > 3) { + /* Delete a byte. */ + pos = secp256k1_rand_int(*len); + memmove(sig + pos, sig + pos + 1, *len - pos - 1); + (*len)--; + return; + } else if (action < 2 && *len < 2048) { + /* Insert a byte. */ + pos = secp256k1_rand_int(1 + *len); + memmove(sig + pos + 1, sig + pos, *len - pos); + sig[pos] = secp256k1_rand_bits(8); + (*len)++; + return; + } else if (action < 4) { + /* Modify a byte. */ + sig[secp256k1_rand_int(*len)] += 1 + secp256k1_rand_int(255); + return; + } else { /* action < 8 */ + /* Modify a bit. */ + sig[secp256k1_rand_int(*len)] ^= 1 << secp256k1_rand_bits(3); + return; + } +} + +static void random_ber_signature(unsigned char *sig, size_t *len, int* certainly_der, int* certainly_not_der) { + int der; + int nlow[2], nlen[2], nlenlen[2], nhbit[2], nhbyte[2], nzlen[2]; + size_t tlen, elen, glen; + int indet; + int n; + + *len = 0; + der = secp256k1_rand_bits(2) == 0; + *certainly_der = der; + *certainly_not_der = 0; + indet = der ? 0 : secp256k1_rand_int(10) == 0; + + for (n = 0; n < 2; n++) { + /* We generate two classes of numbers: nlow==1 "low" ones (up to 32 bytes), nlow==0 "high" ones (32 bytes with 129 top bits set, or larger than 32 bytes) */ + nlow[n] = der ? 1 : (secp256k1_rand_bits(3) != 0); + /* The length of the number in bytes (the first byte of which will always be nonzero) */ + nlen[n] = nlow[n] ? secp256k1_rand_int(33) : 32 + secp256k1_rand_int(200) * secp256k1_rand_int(8) / 8; + CHECK(nlen[n] <= 232); + /* The top bit of the number. */ + nhbit[n] = (nlow[n] == 0 && nlen[n] == 32) ? 1 : (nlen[n] == 0 ? 0 : secp256k1_rand_bits(1)); + /* The top byte of the number (after the potential hardcoded 16 0xFF characters for "high" 32 bytes numbers) */ + nhbyte[n] = nlen[n] == 0 ? 0 : (nhbit[n] ? 128 + secp256k1_rand_bits(7) : 1 + secp256k1_rand_int(127)); + /* The number of zero bytes in front of the number (which is 0 or 1 in case of DER, otherwise we extend up to 300 bytes) */ + nzlen[n] = der ? ((nlen[n] == 0 || nhbit[n]) ? 1 : 0) : (nlow[n] ? secp256k1_rand_int(3) : secp256k1_rand_int(300 - nlen[n]) * secp256k1_rand_int(8) / 8); + if (nzlen[n] > ((nlen[n] == 0 || nhbit[n]) ? 1 : 0)) { + *certainly_not_der = 1; + } + CHECK(nlen[n] + nzlen[n] <= 300); + /* The length of the length descriptor for the number. 0 means short encoding, anything else is long encoding. */ + nlenlen[n] = nlen[n] + nzlen[n] < 128 ? 0 : (nlen[n] + nzlen[n] < 256 ? 1 : 2); + if (!der) { + /* nlenlen[n] max 127 bytes */ + int add = secp256k1_rand_int(127 - nlenlen[n]) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; + nlenlen[n] += add; + if (add != 0) { + *certainly_not_der = 1; + } + } + CHECK(nlen[n] + nzlen[n] + nlenlen[n] <= 427); + } + + /* The total length of the data to go, so far */ + tlen = 2 + nlenlen[0] + nlen[0] + nzlen[0] + 2 + nlenlen[1] + nlen[1] + nzlen[1]; + CHECK(tlen <= 856); + + /* The length of the garbage inside the tuple. */ + elen = (der || indet) ? 0 : secp256k1_rand_int(980 - tlen) * secp256k1_rand_int(8) / 8; + if (elen != 0) { + *certainly_not_der = 1; + } + tlen += elen; + CHECK(tlen <= 980); + + /* The length of the garbage after the end of the tuple. */ + glen = der ? 0 : secp256k1_rand_int(990 - tlen) * secp256k1_rand_int(8) / 8; + if (glen != 0) { + *certainly_not_der = 1; + } + CHECK(tlen + glen <= 990); + + /* Write the tuple header. */ + sig[(*len)++] = 0x30; + if (indet) { + /* Indeterminate length */ + sig[(*len)++] = 0x80; + *certainly_not_der = 1; + } else { + int tlenlen = tlen < 128 ? 0 : (tlen < 256 ? 1 : 2); + if (!der) { + int add = secp256k1_rand_int(127 - tlenlen) * secp256k1_rand_int(16) * secp256k1_rand_int(16) / 256; + tlenlen += add; + if (add != 0) { + *certainly_not_der = 1; + } + } + if (tlenlen == 0) { + /* Short length notation */ + sig[(*len)++] = tlen; + } else { + /* Long length notation */ + sig[(*len)++] = 128 + tlenlen; + assign_big_endian(sig + *len, tlenlen, tlen); + *len += tlenlen; + } + tlen += tlenlen; + } + tlen += 2; + CHECK(tlen + glen <= 1119); + + for (n = 0; n < 2; n++) { + /* Write the integer header. */ + sig[(*len)++] = 0x02; + if (nlenlen[n] == 0) { + /* Short length notation */ + sig[(*len)++] = nlen[n] + nzlen[n]; + } else { + /* Long length notation. */ + sig[(*len)++] = 128 + nlenlen[n]; + assign_big_endian(sig + *len, nlenlen[n], nlen[n] + nzlen[n]); + *len += nlenlen[n]; + } + /* Write zero padding */ + while (nzlen[n] > 0) { + sig[(*len)++] = 0x00; + nzlen[n]--; + } + if (nlen[n] == 32 && !nlow[n]) { + /* Special extra 16 0xFF bytes in "high" 32-byte numbers */ + int i; + for (i = 0; i < 16; i++) { + sig[(*len)++] = 0xFF; + } + nlen[n] -= 16; + } + /* Write first byte of number */ + if (nlen[n] > 0) { + sig[(*len)++] = nhbyte[n]; + nlen[n]--; + } + /* Generate remaining random bytes of number */ + secp256k1_rand_bytes_test(sig + *len, nlen[n]); + *len += nlen[n]; + nlen[n] = 0; + } + + /* Generate random garbage inside tuple. */ + secp256k1_rand_bytes_test(sig + *len, elen); + *len += elen; + + /* Generate end-of-contents bytes. */ + if (indet) { + sig[(*len)++] = 0; + sig[(*len)++] = 0; + tlen += 2; + } + CHECK(tlen + glen <= 1121); + + /* Generate random garbage outside tuple. */ + secp256k1_rand_bytes_test(sig + *len, glen); + *len += glen; + tlen += glen; + CHECK(tlen <= 1121); + CHECK(tlen == *len); +} + +void run_ecdsa_der_parse(void) { + int i,j; + for (i = 0; i < 200 * count; i++) { + unsigned char buffer[2048]; + size_t buflen = 0; + int certainly_der = 0; + int certainly_not_der = 0; + random_ber_signature(buffer, &buflen, &certainly_der, &certainly_not_der); + CHECK(buflen <= 2048); + for (j = 0; j < 16; j++) { + int ret = 0; + if (j > 0) { + damage_array(buffer, &buflen); + /* We don't know anything anymore about the DERness of the result */ + certainly_der = 0; + certainly_not_der = 0; + } + ret = test_ecdsa_der_parse(buffer, buflen, certainly_der, certainly_not_der); + if (ret != 0) { + size_t k; + fprintf(stderr, "Failure %x on ", ret); + for (k = 0; k < buflen; k++) { + fprintf(stderr, "%02x ", buffer[k]); + } + fprintf(stderr, "\n"); + } + CHECK(ret == 0); + } + } +} + +/* Tests several edge cases. */ +void test_ecdsa_edge_cases(void) { + int t; + secp256k1_ecdsa_signature sig; + + /* Test the case where ECDSA recomputes a point that is infinity. */ + { + secp256k1_gej keyj; + secp256k1_ge key; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_negate(&ss, &ss); + secp256k1_scalar_inverse(&ss, &ss); + secp256k1_scalar_set_int(&sr, 1); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &keyj, &sr); + secp256k1_ge_set_gej(&key, &keyj); + msg = ss; + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + } + + /* Verify signature with r of zero fails. */ + { + const unsigned char pubkey_mods_zero[33] = { + 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, + 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, + 0x41 + }; + secp256k1_ge key; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_set_int(&msg, 0); + secp256k1_scalar_set_int(&sr, 0); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey_mods_zero, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + } + + /* Verify signature with s of zero fails. */ + { + const unsigned char pubkey[33] = { + 0x02, 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, + 0x01 + }; + secp256k1_ge key; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 0); + secp256k1_scalar_set_int(&msg, 0); + secp256k1_scalar_set_int(&sr, 1); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + } + + /* Verify signature with message 0 passes. */ + { + const unsigned char pubkey[33] = { + 0x02, 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, + 0x02 + }; + const unsigned char pubkey2[33] = { + 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, + 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, + 0x43 + }; + secp256k1_ge key; + secp256k1_ge key2; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 2); + secp256k1_scalar_set_int(&msg, 0); + secp256k1_scalar_set_int(&sr, 2); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + secp256k1_scalar_negate(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + secp256k1_scalar_set_int(&ss, 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); + } + + /* Verify signature with message 1 passes. */ + { + const unsigned char pubkey[33] = { + 0x02, 0x14, 0x4e, 0x5a, 0x58, 0xef, 0x5b, 0x22, + 0x6f, 0xd2, 0xe2, 0x07, 0x6a, 0x77, 0xcf, 0x05, + 0xb4, 0x1d, 0xe7, 0x4a, 0x30, 0x98, 0x27, 0x8c, + 0x93, 0xe6, 0xe6, 0x3c, 0x0b, 0xc4, 0x73, 0x76, + 0x25 + }; + const unsigned char pubkey2[33] = { + 0x02, 0x8a, 0xd5, 0x37, 0xed, 0x73, 0xd9, 0x40, + 0x1d, 0xa0, 0x33, 0xd2, 0xdc, 0xf0, 0xaf, 0xae, + 0x34, 0xcf, 0x5f, 0x96, 0x4c, 0x73, 0x28, 0x0f, + 0x92, 0xc0, 0xf6, 0x9d, 0xd9, 0xb2, 0x09, 0x10, + 0x62 + }; + const unsigned char csr[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, + 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xeb + }; + secp256k1_ge key; + secp256k1_ge key2; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_set_int(&msg, 1); + secp256k1_scalar_set_b32(&sr, csr, NULL); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(secp256k1_eckey_pubkey_parse(&key2, pubkey2, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + secp256k1_scalar_negate(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 1); + secp256k1_scalar_set_int(&ss, 2); + secp256k1_scalar_inverse_var(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key2, &msg) == 0); + } + + /* Verify signature with message -1 passes. */ + { + const unsigned char pubkey[33] = { + 0x03, 0xaf, 0x97, 0xff, 0x7d, 0x3a, 0xf6, 0xa0, + 0x02, 0x94, 0xbd, 0x9f, 0x4b, 0x2e, 0xd7, 0x52, + 0x28, 0xdb, 0x49, 0x2a, 0x65, 0xcb, 0x1e, 0x27, + 0x57, 0x9c, 0xba, 0x74, 0x20, 0xd5, 0x1d, 0x20, + 0xf1 + }; + const unsigned char csr[32] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x45, 0x51, 0x23, 0x19, 0x50, 0xb7, 0x5f, 0xc4, + 0x40, 0x2d, 0xa1, 0x72, 0x2f, 0xc9, 0xba, 0xee + }; + secp256k1_ge key; + secp256k1_scalar msg; + secp256k1_scalar sr, ss; + secp256k1_scalar_set_int(&ss, 1); + secp256k1_scalar_set_int(&msg, 1); + secp256k1_scalar_negate(&msg, &msg); + secp256k1_scalar_set_b32(&sr, csr, NULL); + CHECK(secp256k1_eckey_pubkey_parse(&key, pubkey, 33)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + secp256k1_scalar_negate(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 1); + secp256k1_scalar_set_int(&ss, 3); + secp256k1_scalar_inverse_var(&ss, &ss); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sr, &ss, &key, &msg) == 0); + } + + /* Signature where s would be zero. */ + { + secp256k1_pubkey pubkey; + size_t siglen; + int32_t ecount; + unsigned char signature[72]; + static const unsigned char nonce[32] = { + 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, 0x01, + }; + static const unsigned char nonce2[32] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE, + 0xBA,0xAE,0xDC,0xE6,0xAF,0x48,0xA0,0x3B, + 0xBF,0xD2,0x5E,0x8C,0xD0,0x36,0x41,0x40 + }; + const unsigned char key[32] = { + 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, 0x01, + }; + unsigned char msg[32] = { + 0x86, 0x41, 0x99, 0x81, 0x06, 0x23, 0x44, 0x53, + 0xaa, 0x5f, 0x9d, 0x6a, 0x31, 0x78, 0xf4, 0xf7, + 0xb8, 0x12, 0xe0, 0x0b, 0x81, 0x7a, 0x77, 0x62, + 0x65, 0xdf, 0xdd, 0x31, 0xb9, 0x3e, 0x29, 0xa9, + }; + ecount = 0; + secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 0); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 0); + msg[31] = 0xaa; + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce) == 1); + CHECK(ecount == 0); + CHECK(secp256k1_ecdsa_sign(ctx, NULL, msg, key, precomputed_nonce_function, nonce2) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, NULL, key, precomputed_nonce_function, nonce2) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, NULL, precomputed_nonce_function, nonce2) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, precomputed_nonce_function, nonce2) == 1); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, key) == 1); + CHECK(secp256k1_ecdsa_verify(ctx, NULL, msg, &pubkey) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, NULL, &pubkey) == 0); + CHECK(ecount == 5); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, NULL) == 0); + CHECK(ecount == 6); + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 1); + CHECK(ecount == 6); + CHECK(secp256k1_ec_pubkey_create(ctx, &pubkey, NULL) == 0); + CHECK(ecount == 7); + /* That pubkeyload fails via an ARGCHECK is a little odd but makes sense because pubkeys are an opaque data type. */ + CHECK(secp256k1_ecdsa_verify(ctx, &sig, msg, &pubkey) == 0); + CHECK(ecount == 8); + siglen = 72; + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, NULL, &siglen, &sig) == 0); + CHECK(ecount == 9); + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, NULL, &sig) == 0); + CHECK(ecount == 10); + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, NULL) == 0); + CHECK(ecount == 11); + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 1); + CHECK(ecount == 11); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, NULL, signature, siglen) == 0); + CHECK(ecount == 12); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, NULL, siglen) == 0); + CHECK(ecount == 13); + CHECK(secp256k1_ecdsa_signature_parse_der(ctx, &sig, signature, siglen) == 1); + CHECK(ecount == 13); + siglen = 10; + /* Too little room for a signature does not fail via ARGCHECK. */ + CHECK(secp256k1_ecdsa_signature_serialize_der(ctx, signature, &siglen, &sig) == 0); + CHECK(ecount == 13); + ecount = 0; + CHECK(secp256k1_ecdsa_signature_normalize(ctx, NULL, NULL) == 0); + CHECK(ecount == 1); + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, NULL, &sig) == 0); + CHECK(ecount == 2); + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, NULL) == 0); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_signature_serialize_compact(ctx, signature, &sig) == 1); + CHECK(ecount == 3); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, NULL, signature) == 0); + CHECK(ecount == 4); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, NULL) == 0); + CHECK(ecount == 5); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 1); + CHECK(ecount == 5); + memset(signature, 255, 64); + CHECK(secp256k1_ecdsa_signature_parse_compact(ctx, &sig, signature) == 0); + CHECK(ecount == 5); + secp256k1_context_set_illegal_callback(ctx, NULL, NULL); + } + + /* Nonce function corner cases. */ + for (t = 0; t < 2; t++) { + static const unsigned char zero[32] = {0x00}; + int i; + unsigned char key[32]; + unsigned char msg[32]; + secp256k1_ecdsa_signature sig2; + secp256k1_scalar sr[512], ss; + const unsigned char *extra; + extra = t == 0 ? NULL : zero; + memset(msg, 0, 32); + msg[31] = 1; + /* High key results in signature failure. */ + memset(key, 0xFF, 32); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); + CHECK(is_empty_signature(&sig)); + /* Zero key results in signature failure. */ + memset(key, 0, 32); + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, NULL, extra) == 0); + CHECK(is_empty_signature(&sig)); + /* Nonce function failure results in signature failure. */ + key[31] = 1; + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_fail, extra) == 0); + CHECK(is_empty_signature(&sig)); + /* The retry loop successfully makes its way to the first good value. */ + CHECK(secp256k1_ecdsa_sign(ctx, &sig, msg, key, nonce_function_test_retry, extra) == 1); + CHECK(!is_empty_signature(&sig)); + CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, nonce_function_rfc6979, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); + /* The default nonce function is deterministic. */ + CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + CHECK(memcmp(&sig, &sig2, sizeof(sig)) == 0); + /* The default nonce function changes output with different messages. */ + for(i = 0; i < 256; i++) { + int j; + msg[0] = i; + CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); + for (j = 0; j < i; j++) { + CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); + } + } + msg[0] = 0; + msg[31] = 2; + /* The default nonce function changes output with different keys. */ + for(i = 256; i < 512; i++) { + int j; + key[0] = i - 256; + CHECK(secp256k1_ecdsa_sign(ctx, &sig2, msg, key, NULL, extra) == 1); + CHECK(!is_empty_signature(&sig2)); + secp256k1_ecdsa_signature_load(ctx, &sr[i], &ss, &sig2); + for (j = 0; j < i; j++) { + CHECK(!secp256k1_scalar_eq(&sr[i], &sr[j])); + } + } + key[0] = 0; + } + + { + /* Check that optional nonce arguments do not have equivalent effect. */ + const unsigned char zeros[32] = {0}; + unsigned char nonce[32]; + unsigned char nonce2[32]; + unsigned char nonce3[32]; + unsigned char nonce4[32]; + VG_UNDEF(nonce,32); + VG_UNDEF(nonce2,32); + VG_UNDEF(nonce3,32); + VG_UNDEF(nonce4,32); + CHECK(nonce_function_rfc6979(nonce, zeros, zeros, NULL, NULL, 0) == 1); + VG_CHECK(nonce,32); + CHECK(nonce_function_rfc6979(nonce2, zeros, zeros, zeros, NULL, 0) == 1); + VG_CHECK(nonce2,32); + CHECK(nonce_function_rfc6979(nonce3, zeros, zeros, NULL, (void *)zeros, 0) == 1); + VG_CHECK(nonce3,32); + CHECK(nonce_function_rfc6979(nonce4, zeros, zeros, zeros, (void *)zeros, 0) == 1); + VG_CHECK(nonce4,32); + CHECK(memcmp(nonce, nonce2, 32) != 0); + CHECK(memcmp(nonce, nonce3, 32) != 0); + CHECK(memcmp(nonce, nonce4, 32) != 0); + CHECK(memcmp(nonce2, nonce3, 32) != 0); + CHECK(memcmp(nonce2, nonce4, 32) != 0); + CHECK(memcmp(nonce3, nonce4, 32) != 0); + } + + + /* Privkey export where pubkey is the point at infinity. */ + { + unsigned char privkey[300]; + unsigned char seckey[32] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, + 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, + }; + size_t outlen = 300; + CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 0)); + outlen = 300; + CHECK(!ec_privkey_export_der(ctx, privkey, &outlen, seckey, 1)); + } +} + +void run_ecdsa_edge_cases(void) { + test_ecdsa_edge_cases(); +} + +#ifdef ENABLE_OPENSSL_TESTS +EC_KEY *get_openssl_key(const unsigned char *key32) { + unsigned char privkey[300]; + size_t privkeylen; + const unsigned char* pbegin = privkey; + int compr = secp256k1_rand_bits(1); + EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); + CHECK(ec_privkey_export_der(ctx, privkey, &privkeylen, key32, compr)); + CHECK(d2i_ECPrivateKey(&ec_key, &pbegin, privkeylen)); + CHECK(EC_KEY_check_key(ec_key)); + return ec_key; +} + +void test_ecdsa_openssl(void) { + secp256k1_gej qj; + secp256k1_ge q; + secp256k1_scalar sigr, sigs; + secp256k1_scalar one; + secp256k1_scalar msg2; + secp256k1_scalar key, msg; + EC_KEY *ec_key; + unsigned int sigsize = 80; + size_t secp_sigsize = 80; + unsigned char message[32]; + unsigned char signature[80]; + unsigned char key32[32]; + secp256k1_rand256_test(message); + secp256k1_scalar_set_b32(&msg, message, NULL); + random_scalar_order_test(&key); + secp256k1_scalar_get_b32(key32, &key); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &qj, &key); + secp256k1_ge_set_gej(&q, &qj); + ec_key = get_openssl_key(key32); + CHECK(ec_key != NULL); + CHECK(ECDSA_sign(0, message, sizeof(message), signature, &sigsize, ec_key)); + CHECK(secp256k1_ecdsa_sig_parse(&sigr, &sigs, signature, sigsize)); + CHECK(secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg)); + secp256k1_scalar_set_int(&one, 1); + secp256k1_scalar_add(&msg2, &msg, &one); + CHECK(!secp256k1_ecdsa_sig_verify(&ctx->ecmult_ctx, &sigr, &sigs, &q, &msg2)); + + random_sign(&sigr, &sigs, &key, &msg, NULL); + CHECK(secp256k1_ecdsa_sig_serialize(signature, &secp_sigsize, &sigr, &sigs)); + CHECK(ECDSA_verify(0, message, sizeof(message), signature, secp_sigsize, ec_key) == 1); + + EC_KEY_free(ec_key); +} + +void run_ecdsa_openssl(void) { + int i; + for (i = 0; i < 10*count; i++) { + test_ecdsa_openssl(); + } +} +#endif + +#ifdef ENABLE_MODULE_ECDH +# include "modules/ecdh/tests_impl.h" +#endif + +#ifdef ENABLE_MODULE_SCHNORR +# include "modules/schnorr/tests_impl.h" +#endif + +#ifdef ENABLE_MODULE_RECOVERY +# include "modules/recovery/tests_impl.h" +#endif + +int main(int argc, char **argv) { + unsigned char seed16[16] = {0}; + unsigned char run32[32] = {0}; + /* find iteration count */ + if (argc > 1) { + count = strtol(argv[1], NULL, 0); + } + + /* find random seed */ + if (argc > 2) { + int pos = 0; + const char* ch = argv[2]; + while (pos < 16 && ch[0] != 0 && ch[1] != 0) { + unsigned short sh; + if (sscanf(ch, "%2hx", &sh)) { + seed16[pos] = sh; + } else { + break; + } + ch += 2; + pos++; + } + } else { + FILE *frand = fopen("/dev/urandom", "r"); + if ((frand == NULL) || !fread(&seed16, sizeof(seed16), 1, frand)) { + uint64_t t = time(NULL) * (uint64_t)1337; + seed16[0] ^= t; + seed16[1] ^= t >> 8; + seed16[2] ^= t >> 16; + seed16[3] ^= t >> 24; + seed16[4] ^= t >> 32; + seed16[5] ^= t >> 40; + seed16[6] ^= t >> 48; + seed16[7] ^= t >> 56; + } + fclose(frand); + } + secp256k1_rand_seed(seed16); + + printf("test count = %i\n", count); + printf("random seed = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", seed16[0], seed16[1], seed16[2], seed16[3], seed16[4], seed16[5], seed16[6], seed16[7], seed16[8], seed16[9], seed16[10], seed16[11], seed16[12], seed16[13], seed16[14], seed16[15]); + + /* initialize */ + run_context_tests(); + ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + if (secp256k1_rand_bits(1)) { + secp256k1_rand256(run32); + CHECK(secp256k1_context_randomize(ctx, secp256k1_rand_bits(1) ? run32 : NULL)); + } + + run_rand_bits(); + run_rand_int(); + + run_sha256_tests(); + run_hmac_sha256_tests(); + run_rfc6979_hmac_sha256_tests(); + +#ifndef USE_NUM_NONE + /* num tests */ + run_num_smalltests(); +#endif + + /* scalar tests */ + run_scalar_tests(); + + /* field tests */ + run_field_inv(); + run_field_inv_var(); + run_field_inv_all_var(); + run_field_misc(); + run_field_convert(); + run_sqr(); + run_sqrt(); + + /* group tests */ + run_ge(); + run_group_decompress(); + + /* ecmult tests */ + run_wnaf(); + run_point_times_order(); + run_ecmult_chain(); + run_ecmult_constants(); + run_ecmult_gen_blind(); + run_ecmult_const_tests(); + run_ec_combine(); + + /* endomorphism tests */ +#ifdef USE_ENDOMORPHISM + run_endomorphism_tests(); +#endif + + /* EC point parser test */ + run_ec_pubkey_parse_test(); + + /* EC key edge cases */ + run_eckey_edge_case_test(); + +#ifdef ENABLE_MODULE_ECDH + /* ecdh tests */ + run_ecdh_tests(); +#endif + + /* ecdsa tests */ + run_random_pubkeys(); + run_ecdsa_der_parse(); + run_ecdsa_sign_verify(); + run_ecdsa_end_to_end(); + run_ecdsa_edge_cases(); +#ifdef ENABLE_OPENSSL_TESTS + run_ecdsa_openssl(); +#endif + +#ifdef ENABLE_MODULE_SCHNORR + /* Schnorr tests */ + run_schnorr_tests(); +#endif + +#ifdef ENABLE_MODULE_RECOVERY + /* ECDSA pubkey recovery tests */ + run_recovery_tests(); +#endif + + secp256k1_rand256(run32); + printf("random run = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", run32[0], run32[1], run32[2], run32[3], run32[4], run32[5], run32[6], run32[7], run32[8], run32[9], run32[10], run32[11], run32[12], run32[13], run32[14], run32[15]); + + /* shutdown */ + secp256k1_context_destroy(ctx); + + printf("no problems found\n"); + return 0; +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c new file mode 100644 index 00000000..b040bb07 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/tests_exhaustive.c @@ -0,0 +1,470 @@ +/*********************************************************************** + * Copyright (c) 2016 Andrew Poelstra * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include +#include + +#include + +#undef USE_ECMULT_STATIC_PRECOMPUTATION + +#ifndef EXHAUSTIVE_TEST_ORDER +/* see group_impl.h for allowable values */ +#define EXHAUSTIVE_TEST_ORDER 13 +#define EXHAUSTIVE_TEST_LAMBDA 9 /* cube root of 1 mod 13 */ +#endif + +#include "include/secp256k1.h" +#include "group.h" +#include "secp256k1.c" +#include "testrand_impl.h" + +#ifdef ENABLE_MODULE_RECOVERY +#include "src/modules/recovery/main_impl.h" +#include "include/secp256k1_recovery.h" +#endif + +/** stolen from tests.c */ +void ge_equals_ge(const secp256k1_ge *a, const secp256k1_ge *b) { + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + CHECK(secp256k1_fe_equal_var(&a->x, &b->x)); + CHECK(secp256k1_fe_equal_var(&a->y, &b->y)); +} + +void ge_equals_gej(const secp256k1_ge *a, const secp256k1_gej *b) { + secp256k1_fe z2s; + secp256k1_fe u1, u2, s1, s2; + CHECK(a->infinity == b->infinity); + if (a->infinity) { + return; + } + /* Check a.x * b.z^2 == b.x && a.y * b.z^3 == b.y, to avoid inverses. */ + secp256k1_fe_sqr(&z2s, &b->z); + secp256k1_fe_mul(&u1, &a->x, &z2s); + u2 = b->x; secp256k1_fe_normalize_weak(&u2); + secp256k1_fe_mul(&s1, &a->y, &z2s); secp256k1_fe_mul(&s1, &s1, &b->z); + s2 = b->y; secp256k1_fe_normalize_weak(&s2); + CHECK(secp256k1_fe_equal_var(&u1, &u2)); + CHECK(secp256k1_fe_equal_var(&s1, &s2)); +} + +void random_fe(secp256k1_fe *x) { + unsigned char bin[32]; + do { + secp256k1_rand256(bin); + if (secp256k1_fe_set_b32(x, bin)) { + return; + } + } while(1); +} +/** END stolen from tests.c */ + +int secp256k1_nonce_function_smallint(unsigned char *nonce32, const unsigned char *msg32, + const unsigned char *key32, const unsigned char *algo16, + void *data, unsigned int attempt) { + secp256k1_scalar s; + int *idata = data; + (void)msg32; + (void)key32; + (void)algo16; + /* Some nonces cannot be used because they'd cause s and/or r to be zero. + * The signing function has retry logic here that just re-calls the nonce + * function with an increased `attempt`. So if attempt > 0 this means we + * need to change the nonce to avoid an infinite loop. */ + if (attempt > 0) { + *idata = (*idata + 1) % EXHAUSTIVE_TEST_ORDER; + } + secp256k1_scalar_set_int(&s, *idata); + secp256k1_scalar_get_b32(nonce32, &s); + return 1; +} + +#ifdef USE_ENDOMORPHISM +void test_exhaustive_endomorphism(const secp256k1_ge *group, int order) { + int i; + for (i = 0; i < order; i++) { + secp256k1_ge res; + secp256k1_ge_mul_lambda(&res, &group[i]); + ge_equals_ge(&group[i * EXHAUSTIVE_TEST_LAMBDA % EXHAUSTIVE_TEST_ORDER], &res); + } +} +#endif + +void test_exhaustive_addition(const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { + int i, j; + + /* Sanity-check (and check infinity functions) */ + CHECK(secp256k1_ge_is_infinity(&group[0])); + CHECK(secp256k1_gej_is_infinity(&groupj[0])); + for (i = 1; i < order; i++) { + CHECK(!secp256k1_ge_is_infinity(&group[i])); + CHECK(!secp256k1_gej_is_infinity(&groupj[i])); + } + + /* Check all addition formulae */ + for (j = 0; j < order; j++) { + secp256k1_fe fe_inv; + secp256k1_fe_inv(&fe_inv, &groupj[j].z); + for (i = 0; i < order; i++) { + secp256k1_ge zless_gej; + secp256k1_gej tmp; + /* add_var */ + secp256k1_gej_add_var(&tmp, &groupj[i], &groupj[j], NULL); + ge_equals_gej(&group[(i + j) % order], &tmp); + /* add_ge */ + if (j > 0) { + secp256k1_gej_add_ge(&tmp, &groupj[i], &group[j]); + ge_equals_gej(&group[(i + j) % order], &tmp); + } + /* add_ge_var */ + secp256k1_gej_add_ge_var(&tmp, &groupj[i], &group[j], NULL); + ge_equals_gej(&group[(i + j) % order], &tmp); + /* add_zinv_var */ + zless_gej.infinity = groupj[j].infinity; + zless_gej.x = groupj[j].x; + zless_gej.y = groupj[j].y; + secp256k1_gej_add_zinv_var(&tmp, &groupj[i], &zless_gej, &fe_inv); + ge_equals_gej(&group[(i + j) % order], &tmp); + } + } + + /* Check doubling */ + for (i = 0; i < order; i++) { + secp256k1_gej tmp; + if (i > 0) { + secp256k1_gej_double_nonzero(&tmp, &groupj[i], NULL); + ge_equals_gej(&group[(2 * i) % order], &tmp); + } + secp256k1_gej_double_var(&tmp, &groupj[i], NULL); + ge_equals_gej(&group[(2 * i) % order], &tmp); + } + + /* Check negation */ + for (i = 1; i < order; i++) { + secp256k1_ge tmp; + secp256k1_gej tmpj; + secp256k1_ge_neg(&tmp, &group[i]); + ge_equals_ge(&group[order - i], &tmp); + secp256k1_gej_neg(&tmpj, &groupj[i]); + ge_equals_gej(&group[order - i], &tmpj); + } +} + +void test_exhaustive_ecmult(const secp256k1_context *ctx, const secp256k1_ge *group, const secp256k1_gej *groupj, int order) { + int i, j, r_log; + for (r_log = 1; r_log < order; r_log++) { + for (j = 0; j < order; j++) { + for (i = 0; i < order; i++) { + secp256k1_gej tmp; + secp256k1_scalar na, ng; + secp256k1_scalar_set_int(&na, i); + secp256k1_scalar_set_int(&ng, j); + + secp256k1_ecmult(&ctx->ecmult_ctx, &tmp, &groupj[r_log], &na, &ng); + ge_equals_gej(&group[(i * r_log + j) % order], &tmp); + + if (i > 0) { + secp256k1_ecmult_const(&tmp, &group[i], &ng); + ge_equals_gej(&group[(i * j) % order], &tmp); + } + } + } + } +} + +void r_from_k(secp256k1_scalar *r, const secp256k1_ge *group, int k) { + secp256k1_fe x; + unsigned char x_bin[32]; + k %= EXHAUSTIVE_TEST_ORDER; + x = group[k].x; + secp256k1_fe_normalize(&x); + secp256k1_fe_get_b32(x_bin, &x); + secp256k1_scalar_set_b32(r, x_bin, NULL); +} + +void test_exhaustive_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + secp256k1_ge nonconst_ge; + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pk; + secp256k1_scalar sk_s, msg_s, r_s, s_s; + secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int k, should_verify; + unsigned char msg32[32]; + + secp256k1_scalar_set_int(&s_s, s); + secp256k1_scalar_set_int(&r_s, r); + secp256k1_scalar_set_int(&msg_s, msg); + secp256k1_scalar_set_int(&sk_s, key); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + secp256k1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + secp256k1_scalar_set_int(&s_times_k_s, k); + secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !secp256k1_scalar_is_high(&s_s); + + /* Verify by calling verify */ + secp256k1_ecdsa_signature_save(&sig, &r_s, &s_s); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + secp256k1_pubkey_save(&pk, &nonconst_ge); + secp256k1_scalar_get_b32(msg32, &msg_s); + CHECK(should_verify == + secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} + +void test_exhaustive_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + secp256k1_ecdsa_signature sig; + secp256k1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + secp256k1_scalar_set_int(&msg, i); + secp256k1_scalar_set_int(&sk, j); + secp256k1_scalar_get_b32(sk32, &sk); + secp256k1_scalar_get_b32(msg32, &msg); + + secp256k1_ecdsa_sign(ctx, &sig, msg32, sk32, secp256k1_nonce_function_smallint, &k); + + secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } + + /* We would like to verify zero-knowledge here by counting how often every + * possible (s, r) tuple appears, but because the group order is larger + * than the field order, when coercing the x-values to scalar values, some + * appear more often than others, so we are actually not zero-knowledge. + * (This effect also appears in the real code, but the difference is on the + * order of 1/2^128th the field order, so the deviation is not useful to a + * computationally bounded attacker.) + */ +} + +#ifdef ENABLE_MODULE_RECOVERY +void test_exhaustive_recovery_sign(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + int i, j, k; + + /* Loop */ + for (i = 1; i < order; i++) { /* message */ + for (j = 1; j < order; j++) { /* key */ + for (k = 1; k < order; k++) { /* nonce */ + const int starting_k = k; + secp256k1_fe r_dot_y_normalized; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + secp256k1_scalar sk, msg, r, s, expected_r; + unsigned char sk32[32], msg32[32]; + int expected_recid; + int recid; + secp256k1_scalar_set_int(&msg, i); + secp256k1_scalar_set_int(&sk, j); + secp256k1_scalar_get_b32(sk32, &sk); + secp256k1_scalar_get_b32(msg32, &msg); + + secp256k1_ecdsa_sign_recoverable(ctx, &rsig, msg32, sk32, secp256k1_nonce_function_smallint, &k); + + /* Check directly */ + secp256k1_ecdsa_recoverable_signature_load(ctx, &r, &s, &recid, &rsig); + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + /* In computing the recid, there is an overflow condition that is disabled in + * scalar_low_impl.h `secp256k1_scalar_set_b32` because almost every r.y value + * will exceed the group order, and our signing code always holds out for r + * values that don't overflow, so with a proper overflow check the tests would + * loop indefinitely. */ + r_dot_y_normalized = group[k].y; + secp256k1_fe_normalize(&r_dot_y_normalized); + /* Also the recovery id is flipped depending if we hit the low-s branch */ + if ((k * s) % order == (i + r * j) % order) { + expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 1 : 0; + } else { + expected_recid = secp256k1_fe_is_odd(&r_dot_y_normalized) ? 0 : 1; + } + CHECK(recid == expected_recid); + + /* Convert to a standard sig then check */ + secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + secp256k1_ecdsa_signature_load(ctx, &r, &s, &sig); + /* Note that we compute expected_r *after* signing -- this is important + * because our nonce-computing function function might change k during + * signing. */ + r_from_k(&expected_r, group, k); + CHECK(r == expected_r); + CHECK((k * s) % order == (i + r * j) % order || + (k * (EXHAUSTIVE_TEST_ORDER - s)) % order == (i + r * j) % order); + + /* Overflow means we've tried every possible nonce */ + if (k < starting_k) { + break; + } + } + } + } +} + +void test_exhaustive_recovery_verify(const secp256k1_context *ctx, const secp256k1_ge *group, int order) { + /* This is essentially a copy of test_exhaustive_verify, with recovery added */ + int s, r, msg, key; + for (s = 1; s < order; s++) { + for (r = 1; r < order; r++) { + for (msg = 1; msg < order; msg++) { + for (key = 1; key < order; key++) { + secp256k1_ge nonconst_ge; + secp256k1_ecdsa_recoverable_signature rsig; + secp256k1_ecdsa_signature sig; + secp256k1_pubkey pk; + secp256k1_scalar sk_s, msg_s, r_s, s_s; + secp256k1_scalar s_times_k_s, msg_plus_r_times_sk_s; + int recid = 0; + int k, should_verify; + unsigned char msg32[32]; + + secp256k1_scalar_set_int(&s_s, s); + secp256k1_scalar_set_int(&r_s, r); + secp256k1_scalar_set_int(&msg_s, msg); + secp256k1_scalar_set_int(&sk_s, key); + secp256k1_scalar_get_b32(msg32, &msg_s); + + /* Verify by hand */ + /* Run through every k value that gives us this r and check that *one* works. + * Note there could be none, there could be multiple, ECDSA is weird. */ + should_verify = 0; + for (k = 0; k < order; k++) { + secp256k1_scalar check_x_s; + r_from_k(&check_x_s, group, k); + if (r_s == check_x_s) { + secp256k1_scalar_set_int(&s_times_k_s, k); + secp256k1_scalar_mul(&s_times_k_s, &s_times_k_s, &s_s); + secp256k1_scalar_mul(&msg_plus_r_times_sk_s, &r_s, &sk_s); + secp256k1_scalar_add(&msg_plus_r_times_sk_s, &msg_plus_r_times_sk_s, &msg_s); + should_verify |= secp256k1_scalar_eq(&s_times_k_s, &msg_plus_r_times_sk_s); + } + } + /* nb we have a "high s" rule */ + should_verify &= !secp256k1_scalar_is_high(&s_s); + + /* We would like to try recovering the pubkey and checking that it matches, + * but pubkey recovery is impossible in the exhaustive tests (the reason + * being that there are 12 nonzero r values, 12 nonzero points, and no + * overlap between the sets, so there are no valid signatures). */ + + /* Verify by converting to a standard signature and calling verify */ + secp256k1_ecdsa_recoverable_signature_save(&rsig, &r_s, &s_s, recid); + secp256k1_ecdsa_recoverable_signature_convert(ctx, &sig, &rsig); + memcpy(&nonconst_ge, &group[sk_s], sizeof(nonconst_ge)); + secp256k1_pubkey_save(&pk, &nonconst_ge); + CHECK(should_verify == + secp256k1_ecdsa_verify(ctx, &sig, msg32, &pk)); + } + } + } + } +} +#endif + +int main(void) { + int i; + secp256k1_gej groupj[EXHAUSTIVE_TEST_ORDER]; + secp256k1_ge group[EXHAUSTIVE_TEST_ORDER]; + + /* Build context */ + secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); + + /* TODO set z = 1, then do num_tests runs with random z values */ + + /* Generate the entire group */ + secp256k1_gej_set_infinity(&groupj[0]); + secp256k1_ge_set_gej(&group[0], &groupj[0]); + for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) { + /* Set a different random z-value for each Jacobian point */ + secp256k1_fe z; + random_fe(&z); + + secp256k1_gej_add_ge(&groupj[i], &groupj[i - 1], &secp256k1_ge_const_g); + secp256k1_ge_set_gej(&group[i], &groupj[i]); + secp256k1_gej_rescale(&groupj[i], &z); + + /* Verify against ecmult_gen */ + { + secp256k1_scalar scalar_i; + secp256k1_gej generatedj; + secp256k1_ge generated; + + secp256k1_scalar_set_int(&scalar_i, i); + secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &generatedj, &scalar_i); + secp256k1_ge_set_gej(&generated, &generatedj); + + CHECK(group[i].infinity == 0); + CHECK(generated.infinity == 0); + CHECK(secp256k1_fe_equal_var(&generated.x, &group[i].x)); + CHECK(secp256k1_fe_equal_var(&generated.y, &group[i].y)); + } + } + + /* Run the tests */ +#ifdef USE_ENDOMORPHISM + test_exhaustive_endomorphism(group, EXHAUSTIVE_TEST_ORDER); +#endif + test_exhaustive_addition(group, groupj, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_ecmult(ctx, group, groupj, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); + +#ifdef ENABLE_MODULE_RECOVERY + test_exhaustive_recovery_sign(ctx, group, EXHAUSTIVE_TEST_ORDER); + test_exhaustive_recovery_verify(ctx, group, EXHAUSTIVE_TEST_ORDER); +#endif + + secp256k1_context_destroy(ctx); + return 0; +} + diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h new file mode 100644 index 00000000..4092a86c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/util.h @@ -0,0 +1,113 @@ +/********************************************************************** + * Copyright (c) 2013, 2014 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or http://www.opensource.org/licenses/mit-license.php.* + **********************************************************************/ + +#ifndef _SECP256K1_UTIL_H_ +#define _SECP256K1_UTIL_H_ + +#if defined HAVE_CONFIG_H +#include "libsecp256k1-config.h" +#endif + +#include +#include +#include + +typedef struct { + void (*fn)(const char *text, void* data); + const void* data; +} secp256k1_callback; + +static SECP256K1_INLINE void secp256k1_callback_call(const secp256k1_callback * const cb, const char * const text) { + cb->fn(text, (void*)cb->data); +} + +#ifdef DETERMINISTIC +#define TEST_FAILURE(msg) do { \ + fprintf(stderr, "%s\n", msg); \ + abort(); \ +} while(0); +#else +#define TEST_FAILURE(msg) do { \ + fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, msg); \ + abort(); \ +} while(0) +#endif + +#ifdef HAVE_BUILTIN_EXPECT +#define EXPECT(x,c) __builtin_expect((x),(c)) +#else +#define EXPECT(x,c) (x) +#endif + +#ifdef DETERMINISTIC +#define CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + TEST_FAILURE("test condition failed"); \ + } \ +} while(0) +#else +#define CHECK(cond) do { \ + if (EXPECT(!(cond), 0)) { \ + TEST_FAILURE("test condition failed: " #cond); \ + } \ +} while(0) +#endif + +/* Like assert(), but when VERIFY is defined, and side-effect safe. */ +#if defined(COVERAGE) +#define VERIFY_CHECK(check) +#define VERIFY_SETUP(stmt) +#elif defined(VERIFY) +#define VERIFY_CHECK CHECK +#define VERIFY_SETUP(stmt) do { stmt; } while(0) +#else +#define VERIFY_CHECK(cond) do { (void)(cond); } while(0) +#define VERIFY_SETUP(stmt) +#endif + +static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_t size) { + void *ret = malloc(size); + if (ret == NULL) { + secp256k1_callback_call(cb, "Out of memory"); + } + return ret; +} + +/* Macro for restrict, when available and not in a VERIFY build. */ +#if defined(SECP256K1_BUILD) && defined(VERIFY) +# define SECP256K1_RESTRICT +#else +# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) +# if SECP256K1_GNUC_PREREQ(3,0) +# define SECP256K1_RESTRICT __restrict__ +# elif (defined(_MSC_VER) && _MSC_VER >= 1400) +# define SECP256K1_RESTRICT __restrict +# else +# define SECP256K1_RESTRICT +# endif +# else +# define SECP256K1_RESTRICT restrict +# endif +#endif + +#if defined(_WIN32) +# define I64FORMAT "I64d" +# define I64uFORMAT "I64u" +#else +# define I64FORMAT "lld" +# define I64uFORMAT "llu" +#endif + +#if defined(HAVE___INT128) +# if defined(__GNUC__) +# define SECP256K1_GNUC_EXT __extension__ +# else +# define SECP256K1_GNUC_EXT +# endif +SECP256K1_GNUC_EXT typedef unsigned __int128 uint128_t; +#endif + +#endif diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/panic_cb.go b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/panic_cb.go new file mode 100644 index 00000000..e0e9034e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/panic_cb.go @@ -0,0 +1,33 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package secp256k1 + +import "C" +import "unsafe" + +// Callbacks for converting libsecp256k1 internal faults into +// recoverable Go panics. + +//export secp256k1GoPanicIllegal +func secp256k1GoPanicIllegal(msg *C.char, data unsafe.Pointer) { + panic("illegal argument: " + C.GoString(msg)) +} + +//export secp256k1GoPanicError +func secp256k1GoPanicError(msg *C.char, data unsafe.Pointer) { + panic("internal error: " + C.GoString(msg)) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/secp256.go b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/secp256.go new file mode 100644 index 00000000..0ffa04fe --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/secp256k1/secp256.go @@ -0,0 +1,130 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package secp256k1 wraps the bitcoin secp256k1 C library. +package secp256k1 + +/* +#cgo CFLAGS: -I./libsecp256k1 +#cgo CFLAGS: -I./libsecp256k1/src/ +#define USE_NUM_NONE +#define USE_FIELD_10X26 +#define USE_FIELD_INV_BUILTIN +#define USE_SCALAR_8X32 +#define USE_SCALAR_INV_BUILTIN +#define NDEBUG +#include "./libsecp256k1/src/secp256k1.c" +#include "./libsecp256k1/src/modules/recovery/main_impl.h" +#include "ext.h" + +typedef void (*callbackFunc) (const char* msg, void* data); +extern void secp256k1GoPanicIllegal(const char* msg, void* data); +extern void secp256k1GoPanicError(const char* msg, void* data); +*/ +import "C" + +import ( + "errors" + "unsafe" +) + +var context *C.secp256k1_context + +func init() { + // around 20 ms on a modern CPU. + context = C.secp256k1_context_create_sign_verify() + C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil) + C.secp256k1_context_set_error_callback(context, C.callbackFunc(C.secp256k1GoPanicError), nil) +} + +var ( + ErrInvalidMsgLen = errors.New("invalid message length, need 32 bytes") + ErrInvalidSignatureLen = errors.New("invalid signature length") + ErrInvalidRecoveryID = errors.New("invalid signature recovery id") + ErrInvalidKey = errors.New("invalid private key") + ErrSignFailed = errors.New("signing failed") + ErrRecoverFailed = errors.New("recovery failed") +) + +// Sign creates a recoverable ECDSA signature. +// The produced signature is in the 65-byte [R || S || V] format where V is 0 or 1. +// +// The caller is responsible for ensuring that msg cannot be chosen +// directly by an attacker. It is usually preferable to use a cryptographic +// hash function on any input before handing it to this function. +func Sign(msg []byte, seckey []byte) ([]byte, error) { + if len(msg) != 32 { + return nil, ErrInvalidMsgLen + } + if len(seckey) != 32 { + return nil, ErrInvalidKey + } + seckeydata := (*C.uchar)(unsafe.Pointer(&seckey[0])) + if C.secp256k1_ec_seckey_verify(context, seckeydata) != 1 { + return nil, ErrInvalidKey + } + + var ( + msgdata = (*C.uchar)(unsafe.Pointer(&msg[0])) + noncefunc = C.secp256k1_nonce_function_rfc6979 + sigstruct C.secp256k1_ecdsa_recoverable_signature + ) + if C.secp256k1_ecdsa_sign_recoverable(context, &sigstruct, msgdata, seckeydata, noncefunc, nil) == 0 { + return nil, ErrSignFailed + } + + var ( + sig = make([]byte, 65) + sigdata = (*C.uchar)(unsafe.Pointer(&sig[0])) + recid C.int + ) + C.secp256k1_ecdsa_recoverable_signature_serialize_compact(context, sigdata, &recid, &sigstruct) + sig[64] = byte(recid) // add back recid to get 65 bytes sig + return sig, nil +} + +// RecoverPubkey returns the the public key of the signer. +// msg must be the 32-byte hash of the message to be signed. +// sig must be a 65-byte compact ECDSA signature containing the +// recovery id as the last element. +func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) { + if len(msg) != 32 { + return nil, ErrInvalidMsgLen + } + if err := checkSignature(sig); err != nil { + return nil, err + } + + var ( + pubkey = make([]byte, 65) + sigdata = (*C.uchar)(unsafe.Pointer(&sig[0])) + msgdata = (*C.uchar)(unsafe.Pointer(&msg[0])) + ) + if C.secp256k1_ecdsa_recover_pubkey(context, (*C.uchar)(unsafe.Pointer(&pubkey[0])), sigdata, msgdata) == 0 { + return nil, ErrRecoverFailed + } + return pubkey, nil +} + +func checkSignature(sig []byte) error { + if len(sig) != 65 { + return ErrInvalidSignatureLen + } + if sig[64] >= 4 { + return ErrInvalidRecoveryID + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/LICENSE b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/LICENSE new file mode 100644 index 00000000..6a66aea5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/PATENTS b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/doc.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/doc.go new file mode 100644 index 00000000..3dab530f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/doc.go @@ -0,0 +1,66 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package sha3 implements the SHA-3 fixed-output-length hash functions and +// the SHAKE variable-output-length hash functions defined by FIPS-202. +// +// Both types of hash function use the "sponge" construction and the Keccak +// permutation. For a detailed specification see http://keccak.noekeon.org/ +// +// +// Guidance +// +// If you aren't sure what function you need, use SHAKE256 with at least 64 +// bytes of output. The SHAKE instances are faster than the SHA3 instances; +// the latter have to allocate memory to conform to the hash.Hash interface. +// +// If you need a secret-key MAC (message authentication code), prepend the +// secret key to the input, hash with SHAKE256 and read at least 32 bytes of +// output. +// +// +// Security strengths +// +// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security +// strength against preimage attacks of x bits. Since they only produce "x" +// bits of output, their collision-resistance is only "x/2" bits. +// +// The SHAKE-256 and -128 functions have a generic security strength of 256 and +// 128 bits against all attacks, provided that at least 2x bits of their output +// is used. Requesting more than 64 or 32 bytes of output, respectively, does +// not increase the collision-resistance of the SHAKE functions. +// +// +// The sponge construction +// +// A sponge builds a pseudo-random function from a public pseudo-random +// permutation, by applying the permutation to a state of "rate + capacity" +// bytes, but hiding "capacity" of the bytes. +// +// A sponge starts out with a zero state. To hash an input using a sponge, up +// to "rate" bytes of the input are XORed into the sponge's state. The sponge +// is then "full" and the permutation is applied to "empty" it. This process is +// repeated until all the input has been "absorbed". The input is then padded. +// The digest is "squeezed" from the sponge in the same way, except that output +// output is copied out instead of input being XORed in. +// +// A sponge is parameterized by its generic security strength, which is equal +// to half its capacity; capacity + rate is equal to the permutation's width. +// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means +// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2. +// +// +// Recommendations +// +// The SHAKE functions are recommended for most new uses. They can produce +// output of arbitrary length. SHAKE256, with an output length of at least +// 64 bytes, provides 256-bit security against all attacks. The Keccak team +// recommends it for most applications upgrading from SHA2-512. (NIST chose a +// much stronger, but much slower, sponge instance for SHA3-512.) +// +// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions. +// They produce output of the same length, with the same security strengths +// against all attacks. This means, in particular, that SHA3-256 only has +// 128-bit collision resistance, because its output length is 32 bytes. +package sha3 diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/hashes.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/hashes.go new file mode 100644 index 00000000..fa0d7b43 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/hashes.go @@ -0,0 +1,71 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3 + +// This file provides functions for creating instances of the SHA-3 +// and SHAKE hash functions, as well as utility functions for hashing +// bytes. + +import ( + "hash" +) + +// NewKeccak256 creates a new Keccak-256 hash. +func NewKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} } + +// NewKeccak512 creates a new Keccak-512 hash. +func NewKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} } + +// New224 creates a new SHA3-224 hash. +// Its generic security strength is 224 bits against preimage attacks, +// and 112 bits against collision attacks. +func New224() hash.Hash { return &state{rate: 144, outputLen: 28, dsbyte: 0x06} } + +// New256 creates a new SHA3-256 hash. +// Its generic security strength is 256 bits against preimage attacks, +// and 128 bits against collision attacks. +func New256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x06} } + +// New384 creates a new SHA3-384 hash. +// Its generic security strength is 384 bits against preimage attacks, +// and 192 bits against collision attacks. +func New384() hash.Hash { return &state{rate: 104, outputLen: 48, dsbyte: 0x06} } + +// New512 creates a new SHA3-512 hash. +// Its generic security strength is 512 bits against preimage attacks, +// and 256 bits against collision attacks. +func New512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x06} } + +// Sum224 returns the SHA3-224 digest of the data. +func Sum224(data []byte) (digest [28]byte) { + h := New224() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum256 returns the SHA3-256 digest of the data. +func Sum256(data []byte) (digest [32]byte) { + h := New256() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum384 returns the SHA3-384 digest of the data. +func Sum384(data []byte) (digest [48]byte) { + h := New384() + h.Write(data) + h.Sum(digest[:0]) + return +} + +// Sum512 returns the SHA3-512 digest of the data. +func Sum512(data []byte) (digest [64]byte) { + h := New512() + h.Write(data) + h.Sum(digest[:0]) + return +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go new file mode 100644 index 00000000..46d03ed3 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf.go @@ -0,0 +1,412 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64 appengine gccgo + +package sha3 + +// rc stores the round constants for use in the ι step. +var rc = [24]uint64{ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +} + +// keccakF1600 applies the Keccak permutation to a 1600b-wide +// state represented as a slice of 25 uint64s. +func keccakF1600(a *[25]uint64) { + // Implementation translated from Keccak-inplace.c + // in the keccak reference code. + var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64 + + for i := 0; i < 24; i += 4 { + // Combines the 5 steps in each round into 2 steps. + // Unrolls 4 rounds per loop and spreads some steps across rounds. + + // Round 1 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[6] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[12] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[18] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[24] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i] + a[6] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[16] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[22] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[3] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[10] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[1] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[7] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[19] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[20] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[11] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[23] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[4] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[5] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[2] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[8] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[14] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[15] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + // Round 2 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[16] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[7] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[23] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[14] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+1] + a[16] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[11] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[2] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[18] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[20] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[6] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[22] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[4] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[15] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[1] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[8] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[24] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[10] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[12] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[3] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[19] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[5] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + // Round 3 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[11] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[22] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[8] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[19] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+2] + a[11] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[1] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[12] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[23] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[15] = bc0 ^ (bc2 &^ bc1) + a[1] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[16] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[2] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[24] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[5] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[6] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[3] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[14] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[20] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[7] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[18] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[4] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[10] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + // Round 4 + bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20] + bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21] + bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22] + bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23] + bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24] + d0 = bc4 ^ (bc1<<1 | bc1>>63) + d1 = bc0 ^ (bc2<<1 | bc2>>63) + d2 = bc1 ^ (bc3<<1 | bc3>>63) + d3 = bc2 ^ (bc4<<1 | bc4>>63) + d4 = bc3 ^ (bc0<<1 | bc0>>63) + + bc0 = a[0] ^ d0 + t = a[1] ^ d1 + bc1 = t<<44 | t>>(64-44) + t = a[2] ^ d2 + bc2 = t<<43 | t>>(64-43) + t = a[3] ^ d3 + bc3 = t<<21 | t>>(64-21) + t = a[4] ^ d4 + bc4 = t<<14 | t>>(64-14) + a[0] = bc0 ^ (bc2 &^ bc1) ^ rc[i+3] + a[1] = bc1 ^ (bc3 &^ bc2) + a[2] = bc2 ^ (bc4 &^ bc3) + a[3] = bc3 ^ (bc0 &^ bc4) + a[4] = bc4 ^ (bc1 &^ bc0) + + t = a[5] ^ d0 + bc2 = t<<3 | t>>(64-3) + t = a[6] ^ d1 + bc3 = t<<45 | t>>(64-45) + t = a[7] ^ d2 + bc4 = t<<61 | t>>(64-61) + t = a[8] ^ d3 + bc0 = t<<28 | t>>(64-28) + t = a[9] ^ d4 + bc1 = t<<20 | t>>(64-20) + a[5] = bc0 ^ (bc2 &^ bc1) + a[6] = bc1 ^ (bc3 &^ bc2) + a[7] = bc2 ^ (bc4 &^ bc3) + a[8] = bc3 ^ (bc0 &^ bc4) + a[9] = bc4 ^ (bc1 &^ bc0) + + t = a[10] ^ d0 + bc4 = t<<18 | t>>(64-18) + t = a[11] ^ d1 + bc0 = t<<1 | t>>(64-1) + t = a[12] ^ d2 + bc1 = t<<6 | t>>(64-6) + t = a[13] ^ d3 + bc2 = t<<25 | t>>(64-25) + t = a[14] ^ d4 + bc3 = t<<8 | t>>(64-8) + a[10] = bc0 ^ (bc2 &^ bc1) + a[11] = bc1 ^ (bc3 &^ bc2) + a[12] = bc2 ^ (bc4 &^ bc3) + a[13] = bc3 ^ (bc0 &^ bc4) + a[14] = bc4 ^ (bc1 &^ bc0) + + t = a[15] ^ d0 + bc1 = t<<36 | t>>(64-36) + t = a[16] ^ d1 + bc2 = t<<10 | t>>(64-10) + t = a[17] ^ d2 + bc3 = t<<15 | t>>(64-15) + t = a[18] ^ d3 + bc4 = t<<56 | t>>(64-56) + t = a[19] ^ d4 + bc0 = t<<27 | t>>(64-27) + a[15] = bc0 ^ (bc2 &^ bc1) + a[16] = bc1 ^ (bc3 &^ bc2) + a[17] = bc2 ^ (bc4 &^ bc3) + a[18] = bc3 ^ (bc0 &^ bc4) + a[19] = bc4 ^ (bc1 &^ bc0) + + t = a[20] ^ d0 + bc3 = t<<41 | t>>(64-41) + t = a[21] ^ d1 + bc4 = t<<2 | t>>(64-2) + t = a[22] ^ d2 + bc0 = t<<62 | t>>(64-62) + t = a[23] ^ d3 + bc1 = t<<55 | t>>(64-55) + t = a[24] ^ d4 + bc2 = t<<39 | t>>(64-39) + a[20] = bc0 ^ (bc2 &^ bc1) + a[21] = bc1 ^ (bc3 &^ bc2) + a[22] = bc2 ^ (bc4 &^ bc3) + a[23] = bc3 ^ (bc0 &^ bc4) + a[24] = bc4 ^ (bc1 &^ bc0) + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go new file mode 100644 index 00000000..de035c55 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.go @@ -0,0 +1,13 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build amd64,!appengine,!gccgo + +package sha3 + +// This function is implemented in keccakf_amd64.s. + +//go:noescape + +func keccakF1600(state *[25]uint64) diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s new file mode 100644 index 00000000..f88533ac --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/keccakf_amd64.s @@ -0,0 +1,390 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build amd64,!appengine,!gccgo + +// This code was translated into a form compatible with 6a from the public +// domain sources at https://github.com/gvanas/KeccakCodePackage + +// Offsets in state +#define _ba (0*8) +#define _be (1*8) +#define _bi (2*8) +#define _bo (3*8) +#define _bu (4*8) +#define _ga (5*8) +#define _ge (6*8) +#define _gi (7*8) +#define _go (8*8) +#define _gu (9*8) +#define _ka (10*8) +#define _ke (11*8) +#define _ki (12*8) +#define _ko (13*8) +#define _ku (14*8) +#define _ma (15*8) +#define _me (16*8) +#define _mi (17*8) +#define _mo (18*8) +#define _mu (19*8) +#define _sa (20*8) +#define _se (21*8) +#define _si (22*8) +#define _so (23*8) +#define _su (24*8) + +// Temporary registers +#define rT1 AX + +// Round vars +#define rpState DI +#define rpStack SP + +#define rDa BX +#define rDe CX +#define rDi DX +#define rDo R8 +#define rDu R9 + +#define rBa R10 +#define rBe R11 +#define rBi R12 +#define rBo R13 +#define rBu R14 + +#define rCa SI +#define rCe BP +#define rCi rBi +#define rCo rBo +#define rCu R15 + +#define MOVQ_RBI_RCE MOVQ rBi, rCe +#define XORQ_RT1_RCA XORQ rT1, rCa +#define XORQ_RT1_RCE XORQ rT1, rCe +#define XORQ_RBA_RCU XORQ rBa, rCu +#define XORQ_RBE_RCU XORQ rBe, rCu +#define XORQ_RDU_RCU XORQ rDu, rCu +#define XORQ_RDA_RCA XORQ rDa, rCa +#define XORQ_RDE_RCE XORQ rDe, rCe + +#define mKeccakRound(iState, oState, rc, B_RBI_RCE, G_RT1_RCA, G_RT1_RCE, G_RBA_RCU, K_RT1_RCA, K_RT1_RCE, K_RBA_RCU, M_RT1_RCA, M_RT1_RCE, M_RBE_RCU, S_RDU_RCU, S_RDA_RCA, S_RDE_RCE) \ + /* Prepare round */ \ + MOVQ rCe, rDa; \ + ROLQ $1, rDa; \ + \ + MOVQ _bi(iState), rCi; \ + XORQ _gi(iState), rDi; \ + XORQ rCu, rDa; \ + XORQ _ki(iState), rCi; \ + XORQ _mi(iState), rDi; \ + XORQ rDi, rCi; \ + \ + MOVQ rCi, rDe; \ + ROLQ $1, rDe; \ + \ + MOVQ _bo(iState), rCo; \ + XORQ _go(iState), rDo; \ + XORQ rCa, rDe; \ + XORQ _ko(iState), rCo; \ + XORQ _mo(iState), rDo; \ + XORQ rDo, rCo; \ + \ + MOVQ rCo, rDi; \ + ROLQ $1, rDi; \ + \ + MOVQ rCu, rDo; \ + XORQ rCe, rDi; \ + ROLQ $1, rDo; \ + \ + MOVQ rCa, rDu; \ + XORQ rCi, rDo; \ + ROLQ $1, rDu; \ + \ + /* Result b */ \ + MOVQ _ba(iState), rBa; \ + MOVQ _ge(iState), rBe; \ + XORQ rCo, rDu; \ + MOVQ _ki(iState), rBi; \ + MOVQ _mo(iState), rBo; \ + MOVQ _su(iState), rBu; \ + XORQ rDe, rBe; \ + ROLQ $44, rBe; \ + XORQ rDi, rBi; \ + XORQ rDa, rBa; \ + ROLQ $43, rBi; \ + \ + MOVQ rBe, rCa; \ + MOVQ rc, rT1; \ + ORQ rBi, rCa; \ + XORQ rBa, rT1; \ + XORQ rT1, rCa; \ + MOVQ rCa, _ba(oState); \ + \ + XORQ rDu, rBu; \ + ROLQ $14, rBu; \ + MOVQ rBa, rCu; \ + ANDQ rBe, rCu; \ + XORQ rBu, rCu; \ + MOVQ rCu, _bu(oState); \ + \ + XORQ rDo, rBo; \ + ROLQ $21, rBo; \ + MOVQ rBo, rT1; \ + ANDQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _bi(oState); \ + \ + NOTQ rBi; \ + ORQ rBa, rBu; \ + ORQ rBo, rBi; \ + XORQ rBo, rBu; \ + XORQ rBe, rBi; \ + MOVQ rBu, _bo(oState); \ + MOVQ rBi, _be(oState); \ + B_RBI_RCE; \ + \ + /* Result g */ \ + MOVQ _gu(iState), rBe; \ + XORQ rDu, rBe; \ + MOVQ _ka(iState), rBi; \ + ROLQ $20, rBe; \ + XORQ rDa, rBi; \ + ROLQ $3, rBi; \ + MOVQ _bo(iState), rBa; \ + MOVQ rBe, rT1; \ + ORQ rBi, rT1; \ + XORQ rDo, rBa; \ + MOVQ _me(iState), rBo; \ + MOVQ _si(iState), rBu; \ + ROLQ $28, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ga(oState); \ + G_RT1_RCA; \ + \ + XORQ rDe, rBo; \ + ROLQ $45, rBo; \ + MOVQ rBi, rT1; \ + ANDQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _ge(oState); \ + G_RT1_RCE; \ + \ + XORQ rDi, rBu; \ + ROLQ $61, rBu; \ + MOVQ rBu, rT1; \ + ORQ rBa, rT1; \ + XORQ rBo, rT1; \ + MOVQ rT1, _go(oState); \ + \ + ANDQ rBe, rBa; \ + XORQ rBu, rBa; \ + MOVQ rBa, _gu(oState); \ + NOTQ rBu; \ + G_RBA_RCU; \ + \ + ORQ rBu, rBo; \ + XORQ rBi, rBo; \ + MOVQ rBo, _gi(oState); \ + \ + /* Result k */ \ + MOVQ _be(iState), rBa; \ + MOVQ _gi(iState), rBe; \ + MOVQ _ko(iState), rBi; \ + MOVQ _mu(iState), rBo; \ + MOVQ _sa(iState), rBu; \ + XORQ rDi, rBe; \ + ROLQ $6, rBe; \ + XORQ rDo, rBi; \ + ROLQ $25, rBi; \ + MOVQ rBe, rT1; \ + ORQ rBi, rT1; \ + XORQ rDe, rBa; \ + ROLQ $1, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ka(oState); \ + K_RT1_RCA; \ + \ + XORQ rDu, rBo; \ + ROLQ $8, rBo; \ + MOVQ rBi, rT1; \ + ANDQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _ke(oState); \ + K_RT1_RCE; \ + \ + XORQ rDa, rBu; \ + ROLQ $18, rBu; \ + NOTQ rBo; \ + MOVQ rBo, rT1; \ + ANDQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _ki(oState); \ + \ + MOVQ rBu, rT1; \ + ORQ rBa, rT1; \ + XORQ rBo, rT1; \ + MOVQ rT1, _ko(oState); \ + \ + ANDQ rBe, rBa; \ + XORQ rBu, rBa; \ + MOVQ rBa, _ku(oState); \ + K_RBA_RCU; \ + \ + /* Result m */ \ + MOVQ _ga(iState), rBe; \ + XORQ rDa, rBe; \ + MOVQ _ke(iState), rBi; \ + ROLQ $36, rBe; \ + XORQ rDe, rBi; \ + MOVQ _bu(iState), rBa; \ + ROLQ $10, rBi; \ + MOVQ rBe, rT1; \ + MOVQ _mi(iState), rBo; \ + ANDQ rBi, rT1; \ + XORQ rDu, rBa; \ + MOVQ _so(iState), rBu; \ + ROLQ $27, rBa; \ + XORQ rBa, rT1; \ + MOVQ rT1, _ma(oState); \ + M_RT1_RCA; \ + \ + XORQ rDi, rBo; \ + ROLQ $15, rBo; \ + MOVQ rBi, rT1; \ + ORQ rBo, rT1; \ + XORQ rBe, rT1; \ + MOVQ rT1, _me(oState); \ + M_RT1_RCE; \ + \ + XORQ rDo, rBu; \ + ROLQ $56, rBu; \ + NOTQ rBo; \ + MOVQ rBo, rT1; \ + ORQ rBu, rT1; \ + XORQ rBi, rT1; \ + MOVQ rT1, _mi(oState); \ + \ + ORQ rBa, rBe; \ + XORQ rBu, rBe; \ + MOVQ rBe, _mu(oState); \ + \ + ANDQ rBa, rBu; \ + XORQ rBo, rBu; \ + MOVQ rBu, _mo(oState); \ + M_RBE_RCU; \ + \ + /* Result s */ \ + MOVQ _bi(iState), rBa; \ + MOVQ _go(iState), rBe; \ + MOVQ _ku(iState), rBi; \ + XORQ rDi, rBa; \ + MOVQ _ma(iState), rBo; \ + ROLQ $62, rBa; \ + XORQ rDo, rBe; \ + MOVQ _se(iState), rBu; \ + ROLQ $55, rBe; \ + \ + XORQ rDu, rBi; \ + MOVQ rBa, rDu; \ + XORQ rDe, rBu; \ + ROLQ $2, rBu; \ + ANDQ rBe, rDu; \ + XORQ rBu, rDu; \ + MOVQ rDu, _su(oState); \ + \ + ROLQ $39, rBi; \ + S_RDU_RCU; \ + NOTQ rBe; \ + XORQ rDa, rBo; \ + MOVQ rBe, rDa; \ + ANDQ rBi, rDa; \ + XORQ rBa, rDa; \ + MOVQ rDa, _sa(oState); \ + S_RDA_RCA; \ + \ + ROLQ $41, rBo; \ + MOVQ rBi, rDe; \ + ORQ rBo, rDe; \ + XORQ rBe, rDe; \ + MOVQ rDe, _se(oState); \ + S_RDE_RCE; \ + \ + MOVQ rBo, rDi; \ + MOVQ rBu, rDo; \ + ANDQ rBu, rDi; \ + ORQ rBa, rDo; \ + XORQ rBi, rDi; \ + XORQ rBo, rDo; \ + MOVQ rDi, _si(oState); \ + MOVQ rDo, _so(oState) \ + +// func keccakF1600(state *[25]uint64) +TEXT ·keccakF1600(SB), 0, $200-8 + MOVQ state+0(FP), rpState + + // Convert the user state into an internal state + NOTQ _be(rpState) + NOTQ _bi(rpState) + NOTQ _go(rpState) + NOTQ _ki(rpState) + NOTQ _mi(rpState) + NOTQ _sa(rpState) + + // Execute the KeccakF permutation + MOVQ _ba(rpState), rCa + MOVQ _be(rpState), rCe + MOVQ _bu(rpState), rCu + + XORQ _ga(rpState), rCa + XORQ _ge(rpState), rCe + XORQ _gu(rpState), rCu + + XORQ _ka(rpState), rCa + XORQ _ke(rpState), rCe + XORQ _ku(rpState), rCu + + XORQ _ma(rpState), rCa + XORQ _me(rpState), rCe + XORQ _mu(rpState), rCu + + XORQ _sa(rpState), rCa + XORQ _se(rpState), rCe + MOVQ _si(rpState), rDi + MOVQ _so(rpState), rDo + XORQ _su(rpState), rCu + + mKeccakRound(rpState, rpStack, $0x0000000000000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000000008082, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x800000000000808a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000080008000, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000008a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x0000000000000088, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x0000000080008009, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x000000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000008000808b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x800000000000008b, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000000008089, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008003, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000000008002, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000000080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x000000000000800a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x800000008000000a, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x8000000080008081, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000000008080, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpState, rpStack, $0x0000000080000001, MOVQ_RBI_RCE, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBA_RCU, XORQ_RT1_RCA, XORQ_RT1_RCE, XORQ_RBE_RCU, XORQ_RDU_RCU, XORQ_RDA_RCA, XORQ_RDE_RCE) + mKeccakRound(rpStack, rpState, $0x8000000080008008, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP) + + // Revert the internal state to the user state + NOTQ _be(rpState) + NOTQ _bi(rpState) + NOTQ _go(rpState) + NOTQ _ki(rpState) + NOTQ _mi(rpState) + NOTQ _sa(rpState) + + RET diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/register.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/register.go new file mode 100644 index 00000000..3cf6a22e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/register.go @@ -0,0 +1,18 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build go1.4 + +package sha3 + +import ( + "crypto" +) + +func init() { + crypto.RegisterHash(crypto.SHA3_224, New224) + crypto.RegisterHash(crypto.SHA3_256, New256) + crypto.RegisterHash(crypto.SHA3_384, New384) + crypto.RegisterHash(crypto.SHA3_512, New512) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go new file mode 100644 index 00000000..c86167c0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/sha3.go @@ -0,0 +1,193 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3 + +// spongeDirection indicates the direction bytes are flowing through the sponge. +type spongeDirection int + +const ( + // spongeAbsorbing indicates that the sponge is absorbing input. + spongeAbsorbing spongeDirection = iota + // spongeSqueezing indicates that the sponge is being squeezed. + spongeSqueezing +) + +const ( + // maxRate is the maximum size of the internal buffer. SHAKE-256 + // currently needs the largest buffer. + maxRate = 168 +) + +type state struct { + // Generic sponge components. + a [25]uint64 // main state of the hash + buf []byte // points into storage + rate int // the number of bytes of state to use + + // dsbyte contains the "domain separation" bits and the first bit of + // the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the + // SHA-3 and SHAKE functions by appending bitstrings to the message. + // Using a little-endian bit-ordering convention, these are "01" for SHA-3 + // and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the + // padding rule from section 5.1 is applied to pad the message to a multiple + // of the rate, which involves adding a "1" bit, zero or more "0" bits, and + // a final "1" bit. We merge the first "1" bit from the padding into dsbyte, + // giving 00000110b (0x06) and 00011111b (0x1f). + // [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf + // "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and + // Extendable-Output Functions (May 2014)" + dsbyte byte + storage [maxRate]byte + + // Specific to SHA-3 and SHAKE. + fixedOutput bool // whether this is a fixed-output-length instance + outputLen int // the default output size in bytes + state spongeDirection // whether the sponge is absorbing or squeezing +} + +// BlockSize returns the rate of sponge underlying this hash function. +func (d *state) BlockSize() int { return d.rate } + +// Size returns the output size of the hash function in bytes. +func (d *state) Size() int { return d.outputLen } + +// Reset clears the internal state by zeroing the sponge state and +// the byte buffer, and setting Sponge.state to absorbing. +func (d *state) Reset() { + // Zero the permutation's state. + for i := range d.a { + d.a[i] = 0 + } + d.state = spongeAbsorbing + d.buf = d.storage[:0] +} + +func (d *state) clone() *state { + ret := *d + if ret.state == spongeAbsorbing { + ret.buf = ret.storage[:len(ret.buf)] + } else { + ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate] + } + + return &ret +} + +// permute applies the KeccakF-1600 permutation. It handles +// any input-output buffering. +func (d *state) permute() { + switch d.state { + case spongeAbsorbing: + // If we're absorbing, we need to xor the input into the state + // before applying the permutation. + xorIn(d, d.buf) + d.buf = d.storage[:0] + keccakF1600(&d.a) + case spongeSqueezing: + // If we're squeezing, we need to apply the permutatin before + // copying more output. + keccakF1600(&d.a) + d.buf = d.storage[:d.rate] + copyOut(d, d.buf) + } +} + +// pads appends the domain separation bits in dsbyte, applies +// the multi-bitrate 10..1 padding rule, and permutes the state. +func (d *state) padAndPermute(dsbyte byte) { + if d.buf == nil { + d.buf = d.storage[:0] + } + // Pad with this instance's domain-separator bits. We know that there's + // at least one byte of space in d.buf because, if it were full, + // permute would have been called to empty it. dsbyte also contains the + // first one bit for the padding. See the comment in the state struct. + d.buf = append(d.buf, dsbyte) + zerosStart := len(d.buf) + d.buf = d.storage[:d.rate] + for i := zerosStart; i < d.rate; i++ { + d.buf[i] = 0 + } + // This adds the final one bit for the padding. Because of the way that + // bits are numbered from the LSB upwards, the final bit is the MSB of + // the last byte. + d.buf[d.rate-1] ^= 0x80 + // Apply the permutation + d.permute() + d.state = spongeSqueezing + d.buf = d.storage[:d.rate] + copyOut(d, d.buf) +} + +// Write absorbs more data into the hash's state. It produces an error +// if more data is written to the ShakeHash after writing +func (d *state) Write(p []byte) (written int, err error) { + if d.state != spongeAbsorbing { + panic("sha3: write to sponge after read") + } + if d.buf == nil { + d.buf = d.storage[:0] + } + written = len(p) + + for len(p) > 0 { + if len(d.buf) == 0 && len(p) >= d.rate { + // The fast path; absorb a full "rate" bytes of input and apply the permutation. + xorIn(d, p[:d.rate]) + p = p[d.rate:] + keccakF1600(&d.a) + } else { + // The slow path; buffer the input until we can fill the sponge, and then xor it in. + todo := d.rate - len(d.buf) + if todo > len(p) { + todo = len(p) + } + d.buf = append(d.buf, p[:todo]...) + p = p[todo:] + + // If the sponge is full, apply the permutation. + if len(d.buf) == d.rate { + d.permute() + } + } + } + + return +} + +// Read squeezes an arbitrary number of bytes from the sponge. +func (d *state) Read(out []byte) (n int, err error) { + // If we're still absorbing, pad and apply the permutation. + if d.state == spongeAbsorbing { + d.padAndPermute(d.dsbyte) + } + + n = len(out) + + // Now, do the squeezing. + for len(out) > 0 { + n := copy(out, d.buf) + d.buf = d.buf[n:] + out = out[n:] + + // Apply the permutation if we've squeezed the sponge dry. + if len(d.buf) == 0 { + d.permute() + } + } + + return +} + +// Sum applies padding to the hash state and then squeezes out the desired +// number of output bytes. +func (d *state) Sum(in []byte) []byte { + // Make a copy of the original hash so that caller can keep writing + // and summing. + dup := d.clone() + hash := make([]byte, dup.outputLen) + dup.Read(hash) + return append(in, hash...) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/shake.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/shake.go new file mode 100644 index 00000000..841f9860 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/shake.go @@ -0,0 +1,60 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3 + +// This file defines the ShakeHash interface, and provides +// functions for creating SHAKE instances, as well as utility +// functions for hashing bytes to arbitrary-length output. + +import ( + "io" +) + +// ShakeHash defines the interface to hash functions that +// support arbitrary-length output. +type ShakeHash interface { + // Write absorbs more data into the hash's state. It panics if input is + // written to it after output has been read from it. + io.Writer + + // Read reads more output from the hash; reading affects the hash's + // state. (ShakeHash.Read is thus very different from Hash.Sum) + // It never returns an error. + io.Reader + + // Clone returns a copy of the ShakeHash in its current state. + Clone() ShakeHash + + // Reset resets the ShakeHash to its initial state. + Reset() +} + +func (d *state) Clone() ShakeHash { + return d.clone() +} + +// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash. +// Its generic security strength is 128 bits against all attacks if at +// least 32 bytes of its output are used. +func NewShake128() ShakeHash { return &state{rate: 168, dsbyte: 0x1f} } + +// NewShake256 creates a new SHAKE128 variable-output-length ShakeHash. +// Its generic security strength is 256 bits against all attacks if +// at least 64 bytes of its output are used. +func NewShake256() ShakeHash { return &state{rate: 136, dsbyte: 0x1f} } + +// ShakeSum128 writes an arbitrary-length digest of data into hash. +func ShakeSum128(hash, data []byte) { + h := NewShake128() + h.Write(data) + h.Read(hash) +} + +// ShakeSum256 writes an arbitrary-length digest of data into hash. +func ShakeSum256(hash, data []byte) { + h := NewShake256() + h.Write(data) + h.Read(hash) +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go new file mode 100644 index 00000000..46a0d63a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor.go @@ -0,0 +1,16 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !amd64,!386,!ppc64le appengine + +package sha3 + +var ( + xorIn = xorInGeneric + copyOut = copyOutGeneric + xorInUnaligned = xorInGeneric + copyOutUnaligned = copyOutGeneric +) + +const xorImplementationUnaligned = "generic" diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_generic.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_generic.go new file mode 100644 index 00000000..fd35f02e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_generic.go @@ -0,0 +1,28 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sha3 + +import "encoding/binary" + +// xorInGeneric xors the bytes in buf into the state; it +// makes no non-portable assumptions about memory layout +// or alignment. +func xorInGeneric(d *state, buf []byte) { + n := len(buf) / 8 + + for i := 0; i < n; i++ { + a := binary.LittleEndian.Uint64(buf) + d.a[i] ^= a + buf = buf[8:] + } +} + +// copyOutGeneric copies ulint64s to a byte buffer. +func copyOutGeneric(d *state, b []byte) { + for i := 0; len(b) >= 8; i++ { + binary.LittleEndian.PutUint64(b, d.a[i]) + b = b[8:] + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go new file mode 100644 index 00000000..929a486a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/sha3/xor_unaligned.go @@ -0,0 +1,58 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build amd64 386 ppc64le +// +build !appengine + +package sha3 + +import "unsafe" + +func xorInUnaligned(d *state, buf []byte) { + bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0])) + n := len(buf) + if n >= 72 { + d.a[0] ^= bw[0] + d.a[1] ^= bw[1] + d.a[2] ^= bw[2] + d.a[3] ^= bw[3] + d.a[4] ^= bw[4] + d.a[5] ^= bw[5] + d.a[6] ^= bw[6] + d.a[7] ^= bw[7] + d.a[8] ^= bw[8] + } + if n >= 104 { + d.a[9] ^= bw[9] + d.a[10] ^= bw[10] + d.a[11] ^= bw[11] + d.a[12] ^= bw[12] + } + if n >= 136 { + d.a[13] ^= bw[13] + d.a[14] ^= bw[14] + d.a[15] ^= bw[15] + d.a[16] ^= bw[16] + } + if n >= 144 { + d.a[17] ^= bw[17] + } + if n >= 168 { + d.a[18] ^= bw[18] + d.a[19] ^= bw[19] + d.a[20] ^= bw[20] + } +} + +func copyOutUnaligned(d *state, buf []byte) { + ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0])) + copy(buf, ab[:]) +} + +var ( + xorIn = xorInUnaligned + copyOut = copyOutUnaligned +) + +const xorImplementationUnaligned = "unaligned" diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go b/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go new file mode 100644 index 00000000..feec5e7b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/signature_cgo.go @@ -0,0 +1,64 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build !nacl,!js,!nocgo + +package crypto + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "fmt" + + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/crypto/secp256k1" +) + +func Ecrecover(hash, sig []byte) ([]byte, error) { + return secp256k1.RecoverPubkey(hash, sig) +} + +func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { + s, err := Ecrecover(hash, sig) + if err != nil { + return nil, err + } + + x, y := elliptic.Unmarshal(S256(), s) + return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil +} + +// Sign calculates an ECDSA signature. +// +// This function is susceptible to chosen plaintext attacks that can leak +// information about the private key that is used for signing. Callers must +// be aware that the given hash cannot be chosen by an adversery. Common +// solution is to hash any input before calculating the signature. +// +// The produced signature is in the [R || S || V] format where V is 0 or 1. +func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { + if len(hash) != 32 { + return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) + } + seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8) + defer zeroBytes(seckey) + return secp256k1.Sign(hash, seckey) +} + +// S256 returns an instance of the secp256k1 curve. +func S256() elliptic.Curve { + return secp256k1.S256() +} diff --git a/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go b/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go new file mode 100644 index 00000000..a022eef9 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/crypto/signature_nocgo.go @@ -0,0 +1,77 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build nacl js nocgo + +package crypto + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "fmt" + + "github.com/btcsuite/btcd/btcec" +) + +func Ecrecover(hash, sig []byte) ([]byte, error) { + pub, err := SigToPub(hash, sig) + if err != nil { + return nil, err + } + bytes := (*btcec.PublicKey)(pub).SerializeUncompressed() + return bytes, err +} + +func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { + // Convert to btcec input format with 'recovery id' v at the beginning. + btcsig := make([]byte, 65) + btcsig[0] = sig[64] + 27 + copy(btcsig[1:], sig) + + pub, _, err := btcec.RecoverCompact(btcec.S256(), btcsig, hash) + return (*ecdsa.PublicKey)(pub), err +} + +// Sign calculates an ECDSA signature. +// +// This function is susceptible to chosen plaintext attacks that can leak +// information about the private key that is used for signing. Callers must +// be aware that the given hash cannot be chosen by an adversery. Common +// solution is to hash any input before calculating the signature. +// +// The produced signature is in the [R || S || V] format where V is 0 or 1. +func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) { + if len(hash) != 32 { + return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) + } + if prv.Curve != btcec.S256() { + return nil, fmt.Errorf("private key curve is not secp256k1") + } + sig, err := btcec.SignCompact(btcec.S256(), (*btcec.PrivateKey)(prv), hash, false) + if err != nil { + return nil, err + } + // Convert to Ethereum signature format with 'recovery id' v at the end. + v := sig[0] - 27 + copy(sig, sig[1:]) + sig[64] = v + return sig, nil +} + +// S256 returns an instance of the secp256k1 curve. +func S256() elliptic.Curve { + return btcec.S256() +} diff --git a/vendor/github.com/ethereum/go-ethereum/log/CONTRIBUTORS b/vendor/github.com/ethereum/go-ethereum/log/CONTRIBUTORS new file mode 100644 index 00000000..a0866713 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/CONTRIBUTORS @@ -0,0 +1,11 @@ +Contributors to log15: + +- Aaron L +- Alan Shreve +- Chris Hines +- Ciaran Downey +- Dmitry Chestnykh +- Evan Shaw +- Péter Szilágyi +- Trevor Gattis +- Vincent Vanackere diff --git a/vendor/github.com/ethereum/go-ethereum/log/LICENSE b/vendor/github.com/ethereum/go-ethereum/log/LICENSE new file mode 100644 index 00000000..5f0d1fb6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/LICENSE @@ -0,0 +1,13 @@ +Copyright 2014 Alan Shreve + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/ethereum/go-ethereum/log/README.md b/vendor/github.com/ethereum/go-ethereum/log/README.md new file mode 100644 index 00000000..0951b21c --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/README.md @@ -0,0 +1,77 @@ +![obligatory xkcd](http://imgs.xkcd.com/comics/standards.png) + +# log15 [![godoc reference](https://godoc.org/github.com/inconshreveable/log15?status.png)](https://godoc.org/github.com/inconshreveable/log15) [![Build Status](https://travis-ci.org/inconshreveable/log15.svg?branch=master)](https://travis-ci.org/inconshreveable/log15) + +Package log15 provides an opinionated, simple toolkit for best-practice logging in Go (golang) that is both human and machine readable. It is modeled after the Go standard library's [`io`](http://golang.org/pkg/io/) and [`net/http`](http://golang.org/pkg/net/http/) packages and is an alternative to the standard library's [`log`](http://golang.org/pkg/log/) package. + +## Features +- A simple, easy-to-understand API +- Promotes structured logging by encouraging use of key/value pairs +- Child loggers which inherit and add their own private context +- Lazy evaluation of expensive operations +- Simple Handler interface allowing for construction of flexible, custom logging configurations with a tiny API. +- Color terminal support +- Built-in support for logging to files, streams, syslog, and the network +- Support for forking records to multiple handlers, buffering records for output, failing over from failed handler writes, + more + +## Versioning +The API of the master branch of log15 should always be considered unstable. If you want to rely on a stable API, +you must vendor the library. + +## Importing + +```go +import log "github.com/inconshreveable/log15" +``` + +## Examples + +```go +// all loggers can have key/value context +srvlog := log.New("module", "app/server") + +// all log messages can have key/value context +srvlog.Warn("abnormal conn rate", "rate", curRate, "low", lowRate, "high", highRate) + +// child loggers with inherited context +connlog := srvlog.New("raddr", c.RemoteAddr()) +connlog.Info("connection open") + +// lazy evaluation +connlog.Debug("ping remote", "latency", log.Lazy{pingRemote}) + +// flexible configuration +srvlog.SetHandler(log.MultiHandler( + log.StreamHandler(os.Stderr, log.LogfmtFormat()), + log.LvlFilterHandler( + log.LvlError, + log.Must.FileHandler("errors.json", log.JsonFormat())))) +``` + +Will result in output that looks like this: + +``` +WARN[06-17|21:58:10] abnormal conn rate module=app/server rate=0.500 low=0.100 high=0.800 +INFO[06-17|21:58:10] connection open module=app/server raddr=10.0.0.1 +``` + +## Breaking API Changes +The following commits broke API stability. This reference is intended to help you understand the consequences of updating to a newer version +of log15. + +- 57a084d014d4150152b19e4e531399a7145d1540 - Added a `Get()` method to the `Logger` interface to retrieve the current handler +- 93404652ee366648fa622b64d1e2b67d75a3094a - `Record` field `Call` changed to `stack.Call` with switch to `github.com/go-stack/stack` +- a5e7613673c73281f58e15a87d2cf0cf111e8152 - Restored `syslog.Priority` argument to the `SyslogXxx` handler constructors + +## FAQ + +### The varargs style is brittle and error prone! Can I have type safety please? +Yes. Use `log.Ctx`: + +```go +srvlog := log.New(log.Ctx{"module": "app/server"}) +srvlog.Warn("abnormal conn rate", log.Ctx{"rate": curRate, "low": lowRate, "high": highRate}) +``` + +## License +Apache diff --git a/vendor/github.com/ethereum/go-ethereum/log/README_ETHEREUM.md b/vendor/github.com/ethereum/go-ethereum/log/README_ETHEREUM.md new file mode 100644 index 00000000..f6c42ccc --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/README_ETHEREUM.md @@ -0,0 +1,5 @@ +This package is a fork of https://github.com/inconshreveable/log15, with some +minor modifications required by the go-ethereum codebase: + + * Support for log level `trace` + * Modified behavior to exit on `critical` failure diff --git a/vendor/github.com/ethereum/go-ethereum/log/doc.go b/vendor/github.com/ethereum/go-ethereum/log/doc.go new file mode 100644 index 00000000..83ad8c54 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/doc.go @@ -0,0 +1,333 @@ +/* +Package log15 provides an opinionated, simple toolkit for best-practice logging that is +both human and machine readable. It is modeled after the standard library's io and net/http +packages. + +This package enforces you to only log key/value pairs. Keys must be strings. Values may be +any type that you like. The default output format is logfmt, but you may also choose to use +JSON instead if that suits you. Here's how you log: + + log.Info("page accessed", "path", r.URL.Path, "user_id", user.id) + +This will output a line that looks like: + + lvl=info t=2014-05-02T16:07:23-0700 msg="page accessed" path=/org/71/profile user_id=9 + +Getting Started + +To get started, you'll want to import the library: + + import log "github.com/inconshreveable/log15" + + +Now you're ready to start logging: + + func main() { + log.Info("Program starting", "args", os.Args()) + } + + +Convention + +Because recording a human-meaningful message is common and good practice, the first argument to every +logging method is the value to the *implicit* key 'msg'. + +Additionally, the level you choose for a message will be automatically added with the key 'lvl', and so +will the current timestamp with key 't'. + +You may supply any additional context as a set of key/value pairs to the logging function. log15 allows +you to favor terseness, ordering, and speed over safety. This is a reasonable tradeoff for +logging functions. You don't need to explicitly state keys/values, log15 understands that they alternate +in the variadic argument list: + + log.Warn("size out of bounds", "low", lowBound, "high", highBound, "val", val) + +If you really do favor your type-safety, you may choose to pass a log.Ctx instead: + + log.Warn("size out of bounds", log.Ctx{"low": lowBound, "high": highBound, "val": val}) + + +Context loggers + +Frequently, you want to add context to a logger so that you can track actions associated with it. An http +request is a good example. You can easily create new loggers that have context that is automatically included +with each log line: + + requestlogger := log.New("path", r.URL.Path) + + // later + requestlogger.Debug("db txn commit", "duration", txnTimer.Finish()) + +This will output a log line that includes the path context that is attached to the logger: + + lvl=dbug t=2014-05-02T16:07:23-0700 path=/repo/12/add_hook msg="db txn commit" duration=0.12 + + +Handlers + +The Handler interface defines where log lines are printed to and how they are formated. Handler is a +single interface that is inspired by net/http's handler interface: + + type Handler interface { + Log(r *Record) error + } + + +Handlers can filter records, format them, or dispatch to multiple other Handlers. +This package implements a number of Handlers for common logging patterns that are +easily composed to create flexible, custom logging structures. + +Here's an example handler that prints logfmt output to Stdout: + + handler := log.StreamHandler(os.Stdout, log.LogfmtFormat()) + +Here's an example handler that defers to two other handlers. One handler only prints records +from the rpc package in logfmt to standard out. The other prints records at Error level +or above in JSON formatted output to the file /var/log/service.json + + handler := log.MultiHandler( + log.LvlFilterHandler(log.LvlError, log.Must.FileHandler("/var/log/service.json", log.JsonFormat())), + log.MatchFilterHandler("pkg", "app/rpc" log.StdoutHandler()) + ) + +Logging File Names and Line Numbers + +This package implements three Handlers that add debugging information to the +context, CallerFileHandler, CallerFuncHandler and CallerStackHandler. Here's +an example that adds the source file and line number of each logging call to +the context. + + h := log.CallerFileHandler(log.StdoutHandler) + log.Root().SetHandler(h) + ... + log.Error("open file", "err", err) + +This will output a line that looks like: + + lvl=eror t=2014-05-02T16:07:23-0700 msg="open file" err="file not found" caller=data.go:42 + +Here's an example that logs the call stack rather than just the call site. + + h := log.CallerStackHandler("%+v", log.StdoutHandler) + log.Root().SetHandler(h) + ... + log.Error("open file", "err", err) + +This will output a line that looks like: + + lvl=eror t=2014-05-02T16:07:23-0700 msg="open file" err="file not found" stack="[pkg/data.go:42 pkg/cmd/main.go]" + +The "%+v" format instructs the handler to include the path of the source file +relative to the compile time GOPATH. The github.com/go-stack/stack package +documents the full list of formatting verbs and modifiers available. + +Custom Handlers + +The Handler interface is so simple that it's also trivial to write your own. Let's create an +example handler which tries to write to one handler, but if that fails it falls back to +writing to another handler and includes the error that it encountered when trying to write +to the primary. This might be useful when trying to log over a network socket, but if that +fails you want to log those records to a file on disk. + + type BackupHandler struct { + Primary Handler + Secondary Handler + } + + func (h *BackupHandler) Log (r *Record) error { + err := h.Primary.Log(r) + if err != nil { + r.Ctx = append(ctx, "primary_err", err) + return h.Secondary.Log(r) + } + return nil + } + +This pattern is so useful that a generic version that handles an arbitrary number of Handlers +is included as part of this library called FailoverHandler. + +Logging Expensive Operations + +Sometimes, you want to log values that are extremely expensive to compute, but you don't want to pay +the price of computing them if you haven't turned up your logging level to a high level of detail. + +This package provides a simple type to annotate a logging operation that you want to be evaluated +lazily, just when it is about to be logged, so that it would not be evaluated if an upstream Handler +filters it out. Just wrap any function which takes no arguments with the log.Lazy type. For example: + + func factorRSAKey() (factors []int) { + // return the factors of a very large number + } + + log.Debug("factors", log.Lazy{factorRSAKey}) + +If this message is not logged for any reason (like logging at the Error level), then +factorRSAKey is never evaluated. + +Dynamic context values + +The same log.Lazy mechanism can be used to attach context to a logger which you want to be +evaluated when the message is logged, but not when the logger is created. For example, let's imagine +a game where you have Player objects: + + type Player struct { + name string + alive bool + log.Logger + } + +You always want to log a player's name and whether they're alive or dead, so when you create the player +object, you might do: + + p := &Player{name: name, alive: true} + p.Logger = log.New("name", p.name, "alive", p.alive) + +Only now, even after a player has died, the logger will still report they are alive because the logging +context is evaluated when the logger was created. By using the Lazy wrapper, we can defer the evaluation +of whether the player is alive or not to each log message, so that the log records will reflect the player's +current state no matter when the log message is written: + + p := &Player{name: name, alive: true} + isAlive := func() bool { return p.alive } + player.Logger = log.New("name", p.name, "alive", log.Lazy{isAlive}) + +Terminal Format + +If log15 detects that stdout is a terminal, it will configure the default +handler for it (which is log.StdoutHandler) to use TerminalFormat. This format +logs records nicely for your terminal, including color-coded output based +on log level. + +Error Handling + +Becasuse log15 allows you to step around the type system, there are a few ways you can specify +invalid arguments to the logging functions. You could, for example, wrap something that is not +a zero-argument function with log.Lazy or pass a context key that is not a string. Since logging libraries +are typically the mechanism by which errors are reported, it would be onerous for the logging functions +to return errors. Instead, log15 handles errors by making these guarantees to you: + +- Any log record containing an error will still be printed with the error explained to you as part of the log record. + +- Any log record containing an error will include the context key LOG15_ERROR, enabling you to easily +(and if you like, automatically) detect if any of your logging calls are passing bad values. + +Understanding this, you might wonder why the Handler interface can return an error value in its Log method. Handlers +are encouraged to return errors only if they fail to write their log records out to an external source like if the +syslog daemon is not responding. This allows the construction of useful handlers which cope with those failures +like the FailoverHandler. + +Library Use + +log15 is intended to be useful for library authors as a way to provide configurable logging to +users of their library. Best practice for use in a library is to always disable all output for your logger +by default and to provide a public Logger instance that consumers of your library can configure. Like so: + + package yourlib + + import "github.com/inconshreveable/log15" + + var Log = log.New() + + func init() { + Log.SetHandler(log.DiscardHandler()) + } + +Users of your library may then enable it if they like: + + import "github.com/inconshreveable/log15" + import "example.com/yourlib" + + func main() { + handler := // custom handler setup + yourlib.Log.SetHandler(handler) + } + +Best practices attaching logger context + +The ability to attach context to a logger is a powerful one. Where should you do it and why? +I favor embedding a Logger directly into any persistent object in my application and adding +unique, tracing context keys to it. For instance, imagine I am writing a web browser: + + type Tab struct { + url string + render *RenderingContext + // ... + + Logger + } + + func NewTab(url string) *Tab { + return &Tab { + // ... + url: url, + + Logger: log.New("url", url), + } + } + +When a new tab is created, I assign a logger to it with the url of +the tab as context so it can easily be traced through the logs. +Now, whenever we perform any operation with the tab, we'll log with its +embedded logger and it will include the tab title automatically: + + tab.Debug("moved position", "idx", tab.idx) + +There's only one problem. What if the tab url changes? We could +use log.Lazy to make sure the current url is always written, but that +would mean that we couldn't trace a tab's full lifetime through our +logs after the user navigate to a new URL. + +Instead, think about what values to attach to your loggers the +same way you think about what to use as a key in a SQL database schema. +If it's possible to use a natural key that is unique for the lifetime of the +object, do so. But otherwise, log15's ext package has a handy RandId +function to let you generate what you might call "surrogate keys" +They're just random hex identifiers to use for tracing. Back to our +Tab example, we would prefer to set up our Logger like so: + + import logext "github.com/inconshreveable/log15/ext" + + t := &Tab { + // ... + url: url, + } + + t.Logger = log.New("id", logext.RandId(8), "url", log.Lazy{t.getUrl}) + return t + +Now we'll have a unique traceable identifier even across loading new urls, but +we'll still be able to see the tab's current url in the log messages. + +Must + +For all Handler functions which can return an error, there is a version of that +function which will return no error but panics on failure. They are all available +on the Must object. For example: + + log.Must.FileHandler("/path", log.JsonFormat) + log.Must.NetHandler("tcp", ":1234", log.JsonFormat) + +Inspiration and Credit + +All of the following excellent projects inspired the design of this library: + +code.google.com/p/log4go + +github.com/op/go-logging + +github.com/technoweenie/grohl + +github.com/Sirupsen/logrus + +github.com/kr/logfmt + +github.com/spacemonkeygo/spacelog + +golang's stdlib, notably io and net/http + +The Name + +https://xkcd.com/927/ + +*/ +package log diff --git a/vendor/github.com/ethereum/go-ethereum/log/format.go b/vendor/github.com/ethereum/go-ethereum/log/format.go new file mode 100644 index 00000000..6c19c7a5 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/format.go @@ -0,0 +1,363 @@ +package log + +import ( + "bytes" + "encoding/json" + "fmt" + "reflect" + "strconv" + "strings" + "sync" + "sync/atomic" + "time" + "unicode/utf8" +) + +const ( + timeFormat = "2006-01-02T15:04:05-0700" + termTimeFormat = "01-02|15:04:05" + floatFormat = 'f' + termMsgJust = 40 +) + +// locationTrims are trimmed for display to avoid unwieldy log lines. +var locationTrims = []string{ + "github.com/ethereum/go-ethereum/", +} + +// PrintOrigins sets or unsets log location (file:line) printing for terminal +// format output. +func PrintOrigins(print bool) { + if print { + atomic.StoreUint32(&locationEnabled, 1) + } else { + atomic.StoreUint32(&locationEnabled, 0) + } +} + +// locationEnabled is an atomic flag controlling whether the terminal formatter +// should append the log locations too when printing entries. +var locationEnabled uint32 + +// locationLength is the maxmimum path length encountered, which all logs are +// padded to to aid in alignment. +var locationLength uint32 + +// fieldPadding is a global map with maximum field value lengths seen until now +// to allow padding log contexts in a bit smarter way. +var fieldPadding = make(map[string]int) + +// fieldPaddingLock is a global mutex protecting the field padding map. +var fieldPaddingLock sync.RWMutex + +type Format interface { + Format(r *Record) []byte +} + +// FormatFunc returns a new Format object which uses +// the given function to perform record formatting. +func FormatFunc(f func(*Record) []byte) Format { + return formatFunc(f) +} + +type formatFunc func(*Record) []byte + +func (f formatFunc) Format(r *Record) []byte { + return f(r) +} + +// TerminalStringer is an analogous interface to the stdlib stringer, allowing +// own types to have custom shortened serialization formats when printed to the +// screen. +type TerminalStringer interface { + TerminalString() string +} + +// TerminalFormat formats log records optimized for human readability on +// a terminal with color-coded level output and terser human friendly timestamp. +// This format should only be used for interactive programs or while developing. +// +// [TIME] [LEVEL] MESAGE key=value key=value ... +// +// Example: +// +// [May 16 20:58:45] [DBUG] remove route ns=haproxy addr=127.0.0.1:50002 +// +func TerminalFormat(usecolor bool) Format { + return FormatFunc(func(r *Record) []byte { + var color = 0 + if usecolor { + switch r.Lvl { + case LvlCrit: + color = 35 + case LvlError: + color = 31 + case LvlWarn: + color = 33 + case LvlInfo: + color = 32 + case LvlDebug: + color = 36 + case LvlTrace: + color = 34 + } + } + + b := &bytes.Buffer{} + lvl := r.Lvl.AlignedString() + if atomic.LoadUint32(&locationEnabled) != 0 { + // Log origin printing was requested, format the location path and line number + location := fmt.Sprintf("%+v", r.Call) + for _, prefix := range locationTrims { + location = strings.TrimPrefix(location, prefix) + } + // Maintain the maximum location length for fancyer alignment + align := int(atomic.LoadUint32(&locationLength)) + if align < len(location) { + align = len(location) + atomic.StoreUint32(&locationLength, uint32(align)) + } + padding := strings.Repeat(" ", align-len(location)) + + // Assemble and print the log heading + if color > 0 { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s|%s]%s %s ", color, lvl, r.Time.Format(termTimeFormat), location, padding, r.Msg) + } else { + fmt.Fprintf(b, "%s[%s|%s]%s %s ", lvl, r.Time.Format(termTimeFormat), location, padding, r.Msg) + } + } else { + if color > 0 { + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %s ", color, lvl, r.Time.Format(termTimeFormat), r.Msg) + } else { + fmt.Fprintf(b, "%s[%s] %s ", lvl, r.Time.Format(termTimeFormat), r.Msg) + } + } + // try to justify the log output for short messages + length := utf8.RuneCountInString(r.Msg) + if len(r.Ctx) > 0 && length < termMsgJust { + b.Write(bytes.Repeat([]byte{' '}, termMsgJust-length)) + } + // print the keys logfmt style + logfmt(b, r.Ctx, color, true) + return b.Bytes() + }) +} + +// LogfmtFormat prints records in logfmt format, an easy machine-parseable but human-readable +// format for key/value pairs. +// +// For more details see: http://godoc.org/github.com/kr/logfmt +// +func LogfmtFormat() Format { + return FormatFunc(func(r *Record) []byte { + common := []interface{}{r.KeyNames.Time, r.Time, r.KeyNames.Lvl, r.Lvl, r.KeyNames.Msg, r.Msg} + buf := &bytes.Buffer{} + logfmt(buf, append(common, r.Ctx...), 0, false) + return buf.Bytes() + }) +} + +func logfmt(buf *bytes.Buffer, ctx []interface{}, color int, term bool) { + for i := 0; i < len(ctx); i += 2 { + if i != 0 { + buf.WriteByte(' ') + } + + k, ok := ctx[i].(string) + v := formatLogfmtValue(ctx[i+1], term) + if !ok { + k, v = errorKey, formatLogfmtValue(k, term) + } + + // XXX: we should probably check that all of your key bytes aren't invalid + fieldPaddingLock.RLock() + padding := fieldPadding[k] + fieldPaddingLock.RUnlock() + + length := utf8.RuneCountInString(v) + if padding < length { + padding = length + + fieldPaddingLock.Lock() + fieldPadding[k] = padding + fieldPaddingLock.Unlock() + } + if color > 0 { + fmt.Fprintf(buf, "\x1b[%dm%s\x1b[0m=", color, k) + } else { + buf.WriteString(k) + buf.WriteByte('=') + } + buf.WriteString(v) + if i < len(ctx)-2 { + buf.Write(bytes.Repeat([]byte{' '}, padding-length)) + } + } + buf.WriteByte('\n') +} + +// JsonFormat formats log records as JSON objects separated by newlines. +// It is the equivalent of JsonFormatEx(false, true). +func JsonFormat() Format { + return JsonFormatEx(false, true) +} + +// JsonFormatEx formats log records as JSON objects. If pretty is true, +// records will be pretty-printed. If lineSeparated is true, records +// will be logged with a new line between each record. +func JsonFormatEx(pretty, lineSeparated bool) Format { + jsonMarshal := json.Marshal + if pretty { + jsonMarshal = func(v interface{}) ([]byte, error) { + return json.MarshalIndent(v, "", " ") + } + } + + return FormatFunc(func(r *Record) []byte { + props := make(map[string]interface{}) + + props[r.KeyNames.Time] = r.Time + props[r.KeyNames.Lvl] = r.Lvl.String() + props[r.KeyNames.Msg] = r.Msg + + for i := 0; i < len(r.Ctx); i += 2 { + k, ok := r.Ctx[i].(string) + if !ok { + props[errorKey] = fmt.Sprintf("%+v is not a string key", r.Ctx[i]) + } + props[k] = formatJsonValue(r.Ctx[i+1]) + } + + b, err := jsonMarshal(props) + if err != nil { + b, _ = jsonMarshal(map[string]string{ + errorKey: err.Error(), + }) + return b + } + + if lineSeparated { + b = append(b, '\n') + } + + return b + }) +} + +func formatShared(value interface{}) (result interface{}) { + defer func() { + if err := recover(); err != nil { + if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr && v.IsNil() { + result = "nil" + } else { + panic(err) + } + } + }() + + switch v := value.(type) { + case time.Time: + return v.Format(timeFormat) + + case error: + return v.Error() + + case fmt.Stringer: + return v.String() + + default: + return v + } +} + +func formatJsonValue(value interface{}) interface{} { + value = formatShared(value) + switch value.(type) { + case int, int8, int16, int32, int64, float32, float64, uint, uint8, uint16, uint32, uint64, string: + return value + default: + return fmt.Sprintf("%+v", value) + } +} + +// formatValue formats a value for serialization +func formatLogfmtValue(value interface{}, term bool) string { + if value == nil { + return "nil" + } + + if t, ok := value.(time.Time); ok { + // Performance optimization: No need for escaping since the provided + // timeFormat doesn't have any escape characters, and escaping is + // expensive. + return t.Format(timeFormat) + } + if term { + if s, ok := value.(TerminalStringer); ok { + // Custom terminal stringer provided, use that + return escapeString(s.TerminalString()) + } + } + value = formatShared(value) + switch v := value.(type) { + case bool: + return strconv.FormatBool(v) + case float32: + return strconv.FormatFloat(float64(v), floatFormat, 3, 64) + case float64: + return strconv.FormatFloat(v, floatFormat, 3, 64) + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: + return fmt.Sprintf("%d", value) + case string: + return escapeString(v) + default: + return escapeString(fmt.Sprintf("%+v", value)) + } +} + +var stringBufPool = sync.Pool{ + New: func() interface{} { return new(bytes.Buffer) }, +} + +func escapeString(s string) string { + needsQuotes := false + needsEscape := false + for _, r := range s { + if r <= ' ' || r == '=' || r == '"' { + needsQuotes = true + } + if r == '\\' || r == '"' || r == '\n' || r == '\r' || r == '\t' { + needsEscape = true + } + } + if needsEscape == false && needsQuotes == false { + return s + } + e := stringBufPool.Get().(*bytes.Buffer) + e.WriteByte('"') + for _, r := range s { + switch r { + case '\\', '"': + e.WriteByte('\\') + e.WriteByte(byte(r)) + case '\n': + e.WriteString("\\n") + case '\r': + e.WriteString("\\r") + case '\t': + e.WriteString("\\t") + default: + e.WriteRune(r) + } + } + e.WriteByte('"') + var ret string + if needsQuotes { + ret = e.String() + } else { + ret = string(e.Bytes()[1 : e.Len()-1]) + } + e.Reset() + stringBufPool.Put(e) + return ret +} diff --git a/vendor/github.com/ethereum/go-ethereum/log/handler.go b/vendor/github.com/ethereum/go-ethereum/log/handler.go new file mode 100644 index 00000000..d5594b85 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/handler.go @@ -0,0 +1,361 @@ +package log + +import ( + "fmt" + "io" + "net" + "os" + "reflect" + "sync" + + "github.com/go-stack/stack" +) + +// A Logger prints its log records by writing to a Handler. +// The Handler interface defines where and how log records are written. +// Handlers are composable, providing you great flexibility in combining +// them to achieve the logging structure that suits your applications. +type Handler interface { + Log(r *Record) error +} + +// FuncHandler returns a Handler that logs records with the given +// function. +func FuncHandler(fn func(r *Record) error) Handler { + return funcHandler(fn) +} + +type funcHandler func(r *Record) error + +func (h funcHandler) Log(r *Record) error { + return h(r) +} + +// StreamHandler writes log records to an io.Writer +// with the given format. StreamHandler can be used +// to easily begin writing log records to other +// outputs. +// +// StreamHandler wraps itself with LazyHandler and SyncHandler +// to evaluate Lazy objects and perform safe concurrent writes. +func StreamHandler(wr io.Writer, fmtr Format) Handler { + h := FuncHandler(func(r *Record) error { + _, err := wr.Write(fmtr.Format(r)) + return err + }) + return LazyHandler(SyncHandler(h)) +} + +// SyncHandler can be wrapped around a handler to guarantee that +// only a single Log operation can proceed at a time. It's necessary +// for thread-safe concurrent writes. +func SyncHandler(h Handler) Handler { + var mu sync.Mutex + return FuncHandler(func(r *Record) error { + defer mu.Unlock() + mu.Lock() + return h.Log(r) + }) +} + +// FileHandler returns a handler which writes log records to the give file +// using the given format. If the path +// already exists, FileHandler will append to the given file. If it does not, +// FileHandler will create the file with mode 0644. +func FileHandler(path string, fmtr Format) (Handler, error) { + f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + return nil, err + } + return closingHandler{f, StreamHandler(f, fmtr)}, nil +} + +// NetHandler opens a socket to the given address and writes records +// over the connection. +func NetHandler(network, addr string, fmtr Format) (Handler, error) { + conn, err := net.Dial(network, addr) + if err != nil { + return nil, err + } + + return closingHandler{conn, StreamHandler(conn, fmtr)}, nil +} + +// XXX: closingHandler is essentially unused at the moment +// it's meant for a future time when the Handler interface supports +// a possible Close() operation +type closingHandler struct { + io.WriteCloser + Handler +} + +func (h *closingHandler) Close() error { + return h.WriteCloser.Close() +} + +// CallerFileHandler returns a Handler that adds the line number and file of +// the calling function to the context with key "caller". +func CallerFileHandler(h Handler) Handler { + return FuncHandler(func(r *Record) error { + r.Ctx = append(r.Ctx, "caller", fmt.Sprint(r.Call)) + return h.Log(r) + }) +} + +// CallerFuncHandler returns a Handler that adds the calling function name to +// the context with key "fn". +func CallerFuncHandler(h Handler) Handler { + return FuncHandler(func(r *Record) error { + r.Ctx = append(r.Ctx, "fn", formatCall("%+n", r.Call)) + return h.Log(r) + }) +} + +// This function is here to please go vet on Go < 1.8. +func formatCall(format string, c stack.Call) string { + return fmt.Sprintf(format, c) +} + +// CallerStackHandler returns a Handler that adds a stack trace to the context +// with key "stack". The stack trace is formated as a space separated list of +// call sites inside matching []'s. The most recent call site is listed first. +// Each call site is formatted according to format. See the documentation of +// package github.com/go-stack/stack for the list of supported formats. +func CallerStackHandler(format string, h Handler) Handler { + return FuncHandler(func(r *Record) error { + s := stack.Trace().TrimBelow(r.Call).TrimRuntime() + if len(s) > 0 { + r.Ctx = append(r.Ctx, "stack", fmt.Sprintf(format, s)) + } + return h.Log(r) + }) +} + +// FilterHandler returns a Handler that only writes records to the +// wrapped Handler if the given function evaluates true. For example, +// to only log records where the 'err' key is not nil: +// +// logger.SetHandler(FilterHandler(func(r *Record) bool { +// for i := 0; i < len(r.Ctx); i += 2 { +// if r.Ctx[i] == "err" { +// return r.Ctx[i+1] != nil +// } +// } +// return false +// }, h)) +// +func FilterHandler(fn func(r *Record) bool, h Handler) Handler { + return FuncHandler(func(r *Record) error { + if fn(r) { + return h.Log(r) + } + return nil + }) +} + +// MatchFilterHandler returns a Handler that only writes records +// to the wrapped Handler if the given key in the logged +// context matches the value. For example, to only log records +// from your ui package: +// +// log.MatchFilterHandler("pkg", "app/ui", log.StdoutHandler) +// +func MatchFilterHandler(key string, value interface{}, h Handler) Handler { + return FilterHandler(func(r *Record) (pass bool) { + switch key { + case r.KeyNames.Lvl: + return r.Lvl == value + case r.KeyNames.Time: + return r.Time == value + case r.KeyNames.Msg: + return r.Msg == value + } + + for i := 0; i < len(r.Ctx); i += 2 { + if r.Ctx[i] == key { + return r.Ctx[i+1] == value + } + } + return false + }, h) +} + +// LvlFilterHandler returns a Handler that only writes +// records which are less than the given verbosity +// level to the wrapped Handler. For example, to only +// log Error/Crit records: +// +// log.LvlFilterHandler(log.LvlError, log.StdoutHandler) +// +func LvlFilterHandler(maxLvl Lvl, h Handler) Handler { + return FilterHandler(func(r *Record) (pass bool) { + return r.Lvl <= maxLvl + }, h) +} + +// A MultiHandler dispatches any write to each of its handlers. +// This is useful for writing different types of log information +// to different locations. For example, to log to a file and +// standard error: +// +// log.MultiHandler( +// log.Must.FileHandler("/var/log/app.log", log.LogfmtFormat()), +// log.StderrHandler) +// +func MultiHandler(hs ...Handler) Handler { + return FuncHandler(func(r *Record) error { + for _, h := range hs { + // what to do about failures? + h.Log(r) + } + return nil + }) +} + +// A FailoverHandler writes all log records to the first handler +// specified, but will failover and write to the second handler if +// the first handler has failed, and so on for all handlers specified. +// For example you might want to log to a network socket, but failover +// to writing to a file if the network fails, and then to +// standard out if the file write fails: +// +// log.FailoverHandler( +// log.Must.NetHandler("tcp", ":9090", log.JsonFormat()), +// log.Must.FileHandler("/var/log/app.log", log.LogfmtFormat()), +// log.StdoutHandler) +// +// All writes that do not go to the first handler will add context with keys of +// the form "failover_err_{idx}" which explain the error encountered while +// trying to write to the handlers before them in the list. +func FailoverHandler(hs ...Handler) Handler { + return FuncHandler(func(r *Record) error { + var err error + for i, h := range hs { + err = h.Log(r) + if err == nil { + return nil + } else { + r.Ctx = append(r.Ctx, fmt.Sprintf("failover_err_%d", i), err) + } + } + + return err + }) +} + +// ChannelHandler writes all records to the given channel. +// It blocks if the channel is full. Useful for async processing +// of log messages, it's used by BufferedHandler. +func ChannelHandler(recs chan<- *Record) Handler { + return FuncHandler(func(r *Record) error { + recs <- r + return nil + }) +} + +// BufferedHandler writes all records to a buffered +// channel of the given size which flushes into the wrapped +// handler whenever it is available for writing. Since these +// writes happen asynchronously, all writes to a BufferedHandler +// never return an error and any errors from the wrapped handler are ignored. +func BufferedHandler(bufSize int, h Handler) Handler { + recs := make(chan *Record, bufSize) + go func() { + for m := range recs { + _ = h.Log(m) + } + }() + return ChannelHandler(recs) +} + +// LazyHandler writes all values to the wrapped handler after evaluating +// any lazy functions in the record's context. It is already wrapped +// around StreamHandler and SyslogHandler in this library, you'll only need +// it if you write your own Handler. +func LazyHandler(h Handler) Handler { + return FuncHandler(func(r *Record) error { + // go through the values (odd indices) and reassign + // the values of any lazy fn to the result of its execution + hadErr := false + for i := 1; i < len(r.Ctx); i += 2 { + lz, ok := r.Ctx[i].(Lazy) + if ok { + v, err := evaluateLazy(lz) + if err != nil { + hadErr = true + r.Ctx[i] = err + } else { + if cs, ok := v.(stack.CallStack); ok { + v = cs.TrimBelow(r.Call).TrimRuntime() + } + r.Ctx[i] = v + } + } + } + + if hadErr { + r.Ctx = append(r.Ctx, errorKey, "bad lazy") + } + + return h.Log(r) + }) +} + +func evaluateLazy(lz Lazy) (interface{}, error) { + t := reflect.TypeOf(lz.Fn) + + if t.Kind() != reflect.Func { + return nil, fmt.Errorf("INVALID_LAZY, not func: %+v", lz.Fn) + } + + if t.NumIn() > 0 { + return nil, fmt.Errorf("INVALID_LAZY, func takes args: %+v", lz.Fn) + } + + if t.NumOut() == 0 { + return nil, fmt.Errorf("INVALID_LAZY, no func return val: %+v", lz.Fn) + } + + value := reflect.ValueOf(lz.Fn) + results := value.Call([]reflect.Value{}) + if len(results) == 1 { + return results[0].Interface(), nil + } else { + values := make([]interface{}, len(results)) + for i, v := range results { + values[i] = v.Interface() + } + return values, nil + } +} + +// DiscardHandler reports success for all writes but does nothing. +// It is useful for dynamically disabling logging at runtime via +// a Logger's SetHandler method. +func DiscardHandler() Handler { + return FuncHandler(func(r *Record) error { + return nil + }) +} + +// The Must object provides the following Handler creation functions +// which instead of returning an error parameter only return a Handler +// and panic on failure: FileHandler, NetHandler, SyslogHandler, SyslogNetHandler +var Must muster + +func must(h Handler, err error) Handler { + if err != nil { + panic(err) + } + return h +} + +type muster struct{} + +func (m muster) FileHandler(path string, fmtr Format) Handler { + return must(FileHandler(path, fmtr)) +} + +func (m muster) NetHandler(network, addr string, fmtr Format) Handler { + return must(NetHandler(network, addr, fmtr)) +} diff --git a/vendor/github.com/ethereum/go-ethereum/log/handler_glog.go b/vendor/github.com/ethereum/go-ethereum/log/handler_glog.go new file mode 100644 index 00000000..f8b932fd --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/handler_glog.go @@ -0,0 +1,227 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package log + +import ( + "errors" + "fmt" + "regexp" + "runtime" + "strconv" + "strings" + "sync" + "sync/atomic" +) + +// errVmoduleSyntax is returned when a user vmodule pattern is invalid. +var errVmoduleSyntax = errors.New("expect comma-separated list of filename=N") + +// errTraceSyntax is returned when a user backtrace pattern is invalid. +var errTraceSyntax = errors.New("expect file.go:234") + +// GlogHandler is a log handler that mimics the filtering features of Google's +// glog logger: setting global log levels; overriding with callsite pattern +// matches; and requesting backtraces at certain positions. +type GlogHandler struct { + origin Handler // The origin handler this wraps + + level uint32 // Current log level, atomically accessible + override uint32 // Flag whether overrides are used, atomically accessible + backtrace uint32 // Flag whether backtrace location is set + + patterns []pattern // Current list of patterns to override with + siteCache map[uintptr]Lvl // Cache of callsite pattern evaluations + location string // file:line location where to do a stackdump at + lock sync.RWMutex // Lock protecting the override pattern list +} + +// NewGlogHandler creates a new log handler with filtering functionality similar +// to Google's glog logger. The returned handler implements Handler. +func NewGlogHandler(h Handler) *GlogHandler { + return &GlogHandler{ + origin: h, + } +} + +// pattern contains a filter for the Vmodule option, holding a verbosity level +// and a file pattern to match. +type pattern struct { + pattern *regexp.Regexp + level Lvl +} + +// Verbosity sets the glog verbosity ceiling. The verbosity of individual packages +// and source files can be raised using Vmodule. +func (h *GlogHandler) Verbosity(level Lvl) { + atomic.StoreUint32(&h.level, uint32(level)) +} + +// Vmodule sets the glog verbosity pattern. +// +// The syntax of the argument is a comma-separated list of pattern=N, where the +// pattern is a literal file name or "glob" pattern matching and N is a V level. +// +// For instance: +// +// pattern="gopher.go=3" +// sets the V level to 3 in all Go files named "gopher.go" +// +// pattern="foo=3" +// sets V to 3 in all files of any packages whose import path ends in "foo" +// +// pattern="foo/*=3" +// sets V to 3 in all files of any packages whose import path contains "foo" +func (h *GlogHandler) Vmodule(ruleset string) error { + var filter []pattern + for _, rule := range strings.Split(ruleset, ",") { + // Empty strings such as from a trailing comma can be ignored + if len(rule) == 0 { + continue + } + // Ensure we have a pattern = level filter rule + parts := strings.Split(rule, "=") + if len(parts) != 2 { + return errVmoduleSyntax + } + parts[0] = strings.TrimSpace(parts[0]) + parts[1] = strings.TrimSpace(parts[1]) + if len(parts[0]) == 0 || len(parts[1]) == 0 { + return errVmoduleSyntax + } + // Parse the level and if correct, assemble the filter rule + level, err := strconv.Atoi(parts[1]) + if err != nil { + return errVmoduleSyntax + } + if level <= 0 { + continue // Ignore. It's harmless but no point in paying the overhead. + } + // Compile the rule pattern into a regular expression + matcher := ".*" + for _, comp := range strings.Split(parts[0], "/") { + if comp == "*" { + matcher += "(/.*)?" + } else if comp != "" { + matcher += "/" + regexp.QuoteMeta(comp) + } + } + if !strings.HasSuffix(parts[0], ".go") { + matcher += "/[^/]+\\.go" + } + matcher = matcher + "$" + + re, _ := regexp.Compile(matcher) + filter = append(filter, pattern{re, Lvl(level)}) + } + // Swap out the vmodule pattern for the new filter system + h.lock.Lock() + defer h.lock.Unlock() + + h.patterns = filter + h.siteCache = make(map[uintptr]Lvl) + atomic.StoreUint32(&h.override, uint32(len(filter))) + + return nil +} + +// BacktraceAt sets the glog backtrace location. When set to a file and line +// number holding a logging statement, a stack trace will be written to the Info +// log whenever execution hits that statement. +// +// Unlike with Vmodule, the ".go" must be present. +func (h *GlogHandler) BacktraceAt(location string) error { + // Ensure the backtrace location contains two non-empty elements + parts := strings.Split(location, ":") + if len(parts) != 2 { + return errTraceSyntax + } + parts[0] = strings.TrimSpace(parts[0]) + parts[1] = strings.TrimSpace(parts[1]) + if len(parts[0]) == 0 || len(parts[1]) == 0 { + return errTraceSyntax + } + // Ensure the .go prefix is present and the line is valid + if !strings.HasSuffix(parts[0], ".go") { + return errTraceSyntax + } + if _, err := strconv.Atoi(parts[1]); err != nil { + return errTraceSyntax + } + // All seems valid + h.lock.Lock() + defer h.lock.Unlock() + + h.location = location + atomic.StoreUint32(&h.backtrace, uint32(len(location))) + + return nil +} + +// Log implements Handler.Log, filtering a log record through the global, local +// and backtrace filters, finally emitting it if either allow it through. +func (h *GlogHandler) Log(r *Record) error { + // If backtracing is requested, check whether this is the callsite + if atomic.LoadUint32(&h.backtrace) > 0 { + // Everything below here is slow. Although we could cache the call sites the + // same way as for vmodule, backtracing is so rare it's not worth the extra + // complexity. + h.lock.RLock() + match := h.location == r.Call.String() + h.lock.RUnlock() + + if match { + // Callsite matched, raise the log level to info and gather the stacks + r.Lvl = LvlInfo + + buf := make([]byte, 1024*1024) + buf = buf[:runtime.Stack(buf, true)] + r.Msg += "\n\n" + string(buf) + } + } + // If the global log level allows, fast track logging + if atomic.LoadUint32(&h.level) >= uint32(r.Lvl) { + return h.origin.Log(r) + } + // If no local overrides are present, fast track skipping + if atomic.LoadUint32(&h.override) == 0 { + return nil + } + // Check callsite cache for previously calculated log levels + h.lock.RLock() + lvl, ok := h.siteCache[r.Call.PC()] + h.lock.RUnlock() + + // If we didn't cache the callsite yet, calculate it + if !ok { + h.lock.Lock() + for _, rule := range h.patterns { + if rule.pattern.MatchString(fmt.Sprintf("%+s", r.Call)) { + h.siteCache[r.Call.PC()], lvl, ok = rule.level, rule.level, true + break + } + } + // If no rule matched, remember to drop log the next time + if !ok { + h.siteCache[r.Call.PC()] = 0 + } + h.lock.Unlock() + } + if lvl >= r.Lvl { + return h.origin.Log(r) + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/log/handler_go13.go b/vendor/github.com/ethereum/go-ethereum/log/handler_go13.go new file mode 100644 index 00000000..0843ed0e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/handler_go13.go @@ -0,0 +1,26 @@ +// +build !go1.4 + +package log + +import ( + "sync/atomic" + "unsafe" +) + +// swapHandler wraps another handler that may be swapped out +// dynamically at runtime in a thread-safe fashion. +type swapHandler struct { + handler unsafe.Pointer +} + +func (h *swapHandler) Log(r *Record) error { + return h.Get().Log(r) +} + +func (h *swapHandler) Get() Handler { + return *(*Handler)(atomic.LoadPointer(&h.handler)) +} + +func (h *swapHandler) Swap(newHandler Handler) { + atomic.StorePointer(&h.handler, unsafe.Pointer(&newHandler)) +} diff --git a/vendor/github.com/ethereum/go-ethereum/log/handler_go14.go b/vendor/github.com/ethereum/go-ethereum/log/handler_go14.go new file mode 100644 index 00000000..05dedbf2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/handler_go14.go @@ -0,0 +1,23 @@ +// +build go1.4 + +package log + +import "sync/atomic" + +// swapHandler wraps another handler that may be swapped out +// dynamically at runtime in a thread-safe fashion. +type swapHandler struct { + handler atomic.Value +} + +func (h *swapHandler) Log(r *Record) error { + return (*h.handler.Load().(*Handler)).Log(r) +} + +func (h *swapHandler) Swap(newHandler Handler) { + h.handler.Store(&newHandler) +} + +func (h *swapHandler) Get() Handler { + return *h.handler.Load().(*Handler) +} diff --git a/vendor/github.com/ethereum/go-ethereum/log/logger.go b/vendor/github.com/ethereum/go-ethereum/log/logger.go new file mode 100644 index 00000000..15c83a9b --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/logger.go @@ -0,0 +1,240 @@ +package log + +import ( + "fmt" + "os" + "time" + + "github.com/go-stack/stack" +) + +const timeKey = "t" +const lvlKey = "lvl" +const msgKey = "msg" +const errorKey = "LOG15_ERROR" + +type Lvl int + +const ( + LvlCrit Lvl = iota + LvlError + LvlWarn + LvlInfo + LvlDebug + LvlTrace +) + +// Aligned returns a 5-character string containing the name of a Lvl. +func (l Lvl) AlignedString() string { + switch l { + case LvlTrace: + return "TRACE" + case LvlDebug: + return "DEBUG" + case LvlInfo: + return "INFO " + case LvlWarn: + return "WARN " + case LvlError: + return "ERROR" + case LvlCrit: + return "CRIT " + default: + panic("bad level") + } +} + +// Strings returns the name of a Lvl. +func (l Lvl) String() string { + switch l { + case LvlTrace: + return "trce" + case LvlDebug: + return "dbug" + case LvlInfo: + return "info" + case LvlWarn: + return "warn" + case LvlError: + return "eror" + case LvlCrit: + return "crit" + default: + panic("bad level") + } +} + +// Returns the appropriate Lvl from a string name. +// Useful for parsing command line args and configuration files. +func LvlFromString(lvlString string) (Lvl, error) { + switch lvlString { + case "trace", "trce": + return LvlTrace, nil + case "debug", "dbug": + return LvlDebug, nil + case "info": + return LvlInfo, nil + case "warn": + return LvlWarn, nil + case "error", "eror": + return LvlError, nil + case "crit": + return LvlCrit, nil + default: + return LvlDebug, fmt.Errorf("Unknown level: %v", lvlString) + } +} + +// A Record is what a Logger asks its handler to write +type Record struct { + Time time.Time + Lvl Lvl + Msg string + Ctx []interface{} + Call stack.Call + KeyNames RecordKeyNames +} + +type RecordKeyNames struct { + Time string + Msg string + Lvl string +} + +// A Logger writes key/value pairs to a Handler +type Logger interface { + // New returns a new Logger that has this logger's context plus the given context + New(ctx ...interface{}) Logger + + // GetHandler gets the handler associated with the logger. + GetHandler() Handler + + // SetHandler updates the logger to write records to the specified handler. + SetHandler(h Handler) + + // Log a message at the given level with context key/value pairs + Trace(msg string, ctx ...interface{}) + Debug(msg string, ctx ...interface{}) + Info(msg string, ctx ...interface{}) + Warn(msg string, ctx ...interface{}) + Error(msg string, ctx ...interface{}) + Crit(msg string, ctx ...interface{}) +} + +type logger struct { + ctx []interface{} + h *swapHandler +} + +func (l *logger) write(msg string, lvl Lvl, ctx []interface{}) { + l.h.Log(&Record{ + Time: time.Now(), + Lvl: lvl, + Msg: msg, + Ctx: newContext(l.ctx, ctx), + Call: stack.Caller(2), + KeyNames: RecordKeyNames{ + Time: timeKey, + Msg: msgKey, + Lvl: lvlKey, + }, + }) +} + +func (l *logger) New(ctx ...interface{}) Logger { + child := &logger{newContext(l.ctx, ctx), new(swapHandler)} + child.SetHandler(l.h) + return child +} + +func newContext(prefix []interface{}, suffix []interface{}) []interface{} { + normalizedSuffix := normalize(suffix) + newCtx := make([]interface{}, len(prefix)+len(normalizedSuffix)) + n := copy(newCtx, prefix) + copy(newCtx[n:], normalizedSuffix) + return newCtx +} + +func (l *logger) Trace(msg string, ctx ...interface{}) { + l.write(msg, LvlTrace, ctx) +} + +func (l *logger) Debug(msg string, ctx ...interface{}) { + l.write(msg, LvlDebug, ctx) +} + +func (l *logger) Info(msg string, ctx ...interface{}) { + l.write(msg, LvlInfo, ctx) +} + +func (l *logger) Warn(msg string, ctx ...interface{}) { + l.write(msg, LvlWarn, ctx) +} + +func (l *logger) Error(msg string, ctx ...interface{}) { + l.write(msg, LvlError, ctx) +} + +func (l *logger) Crit(msg string, ctx ...interface{}) { + l.write(msg, LvlCrit, ctx) + os.Exit(1) +} + +func (l *logger) GetHandler() Handler { + return l.h.Get() +} + +func (l *logger) SetHandler(h Handler) { + l.h.Swap(h) +} + +func normalize(ctx []interface{}) []interface{} { + // if the caller passed a Ctx object, then expand it + if len(ctx) == 1 { + if ctxMap, ok := ctx[0].(Ctx); ok { + ctx = ctxMap.toArray() + } + } + + // ctx needs to be even because it's a series of key/value pairs + // no one wants to check for errors on logging functions, + // so instead of erroring on bad input, we'll just make sure + // that things are the right length and users can fix bugs + // when they see the output looks wrong + if len(ctx)%2 != 0 { + ctx = append(ctx, nil, errorKey, "Normalized odd number of arguments by adding nil") + } + + return ctx +} + +// Lazy allows you to defer calculation of a logged value that is expensive +// to compute until it is certain that it must be evaluated with the given filters. +// +// Lazy may also be used in conjunction with a Logger's New() function +// to generate a child logger which always reports the current value of changing +// state. +// +// You may wrap any function which takes no arguments to Lazy. It may return any +// number of values of any type. +type Lazy struct { + Fn interface{} +} + +// Ctx is a map of key/value pairs to pass as context to a log function +// Use this only if you really need greater safety around the arguments you pass +// to the logging functions. +type Ctx map[string]interface{} + +func (c Ctx) toArray() []interface{} { + arr := make([]interface{}, len(c)*2) + + i := 0 + for k, v := range c { + arr[i] = k + arr[i+1] = v + i += 2 + } + + return arr +} diff --git a/vendor/github.com/ethereum/go-ethereum/log/root.go b/vendor/github.com/ethereum/go-ethereum/log/root.go new file mode 100644 index 00000000..71b8cef6 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/root.go @@ -0,0 +1,61 @@ +package log + +import ( + "os" +) + +var ( + root = &logger{[]interface{}{}, new(swapHandler)} + StdoutHandler = StreamHandler(os.Stdout, LogfmtFormat()) + StderrHandler = StreamHandler(os.Stderr, LogfmtFormat()) +) + +func init() { + root.SetHandler(DiscardHandler()) +} + +// New returns a new logger with the given context. +// New is a convenient alias for Root().New +func New(ctx ...interface{}) Logger { + return root.New(ctx...) +} + +// Root returns the root logger +func Root() Logger { + return root +} + +// The following functions bypass the exported logger methods (logger.Debug, +// etc.) to keep the call depth the same for all paths to logger.write so +// runtime.Caller(2) always refers to the call site in client code. + +// Trace is a convenient alias for Root().Trace +func Trace(msg string, ctx ...interface{}) { + root.write(msg, LvlTrace, ctx) +} + +// Debug is a convenient alias for Root().Debug +func Debug(msg string, ctx ...interface{}) { + root.write(msg, LvlDebug, ctx) +} + +// Info is a convenient alias for Root().Info +func Info(msg string, ctx ...interface{}) { + root.write(msg, LvlInfo, ctx) +} + +// Warn is a convenient alias for Root().Warn +func Warn(msg string, ctx ...interface{}) { + root.write(msg, LvlWarn, ctx) +} + +// Error is a convenient alias for Root().Error +func Error(msg string, ctx ...interface{}) { + root.write(msg, LvlError, ctx) +} + +// Crit is a convenient alias for Root().Crit +func Crit(msg string, ctx ...interface{}) { + root.write(msg, LvlCrit, ctx) + os.Exit(1) +} diff --git a/vendor/github.com/ethereum/go-ethereum/log/syslog.go b/vendor/github.com/ethereum/go-ethereum/log/syslog.go new file mode 100644 index 00000000..71a17b30 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/log/syslog.go @@ -0,0 +1,57 @@ +// +build !windows,!plan9 + +package log + +import ( + "log/syslog" + "strings" +) + +// SyslogHandler opens a connection to the system syslog daemon by calling +// syslog.New and writes all records to it. +func SyslogHandler(priority syslog.Priority, tag string, fmtr Format) (Handler, error) { + wr, err := syslog.New(priority, tag) + return sharedSyslog(fmtr, wr, err) +} + +// SyslogNetHandler opens a connection to a log daemon over the network and writes +// all log records to it. +func SyslogNetHandler(net, addr string, priority syslog.Priority, tag string, fmtr Format) (Handler, error) { + wr, err := syslog.Dial(net, addr, priority, tag) + return sharedSyslog(fmtr, wr, err) +} + +func sharedSyslog(fmtr Format, sysWr *syslog.Writer, err error) (Handler, error) { + if err != nil { + return nil, err + } + h := FuncHandler(func(r *Record) error { + var syslogFn = sysWr.Info + switch r.Lvl { + case LvlCrit: + syslogFn = sysWr.Crit + case LvlError: + syslogFn = sysWr.Err + case LvlWarn: + syslogFn = sysWr.Warning + case LvlInfo: + syslogFn = sysWr.Info + case LvlDebug: + syslogFn = sysWr.Debug + case LvlTrace: + syslogFn = func(m string) error { return nil } // There's no syslog level for trace + } + + s := strings.TrimSpace(string(fmtr.Format(r))) + return syslogFn(s) + }) + return LazyHandler(&closingHandler{sysWr, h}), nil +} + +func (m muster) SyslogHandler(priority syslog.Priority, tag string, fmtr Format) Handler { + return must(SyslogHandler(priority, tag, fmtr)) +} + +func (m muster) SyslogNetHandler(net, addr string, priority syslog.Priority, tag string, fmtr Format) Handler { + return must(SyslogNetHandler(net, addr, priority, tag, fmtr)) +} diff --git a/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go new file mode 100644 index 00000000..6a145a7a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/params/bootnodes.go @@ -0,0 +1,60 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +// MainnetBootnodes are the enode URLs of the P2P bootstrap nodes running on +// the main Ethereum network. +var MainnetBootnodes = []string{ + + // Ethereum Foundation Go Bootnodes + "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", // IE + "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", // US-WEST + "enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303", // BR + "enode://158f8aab45f6d19c6cbf4a089c2670541a8da11978a2f90dbf6a502a4a3bab80d288afdbeb7ec0ef6d92de563767f3b1ea9e8e334ca711e9f8e2df5a0385e8e6@13.75.154.138:30303", // AU + "enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303", // SG + + // Ethereum Foundation Cpp Bootnodes + "enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303", // DE + +} + +// TestnetBootnodes are the enode URLs of the P2P bootstrap nodes running on the +// Ropsten test network. +var TestnetBootnodes = []string{ + "enode://6ce05930c72abc632c58e2e4324f7c7ea478cec0ed4fa2528982cf34483094e9cbc9216e7aa349691242576d552a2a56aaeae426c5303ded677ce455ba1acd9d@13.84.180.240:30303", // US-TX + "enode://20c9ad97c081d63397d7b685a412227a40e23c8bdc6688c6f37e97cfbc22d2b4d1db1510d8f61e6a8866ad7f0e17c02b14182d37ea7c3c8b9c2683aeb6b733a1@52.169.14.227:30303", // IE +} + +// RinkebyBootnodes are the enode URLs of the P2P bootstrap nodes running on the +// Rinkeby test network. +var RinkebyBootnodes = []string{ + "enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303", // IE +} + +// RinkebyV5Bootnodes are the enode URLs of the P2P bootstrap nodes running on the +// Rinkeby test network for the experimental RLPx v5 topic-discovery network. +var RinkebyV5Bootnodes = []string{ + "enode://a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf@52.169.42.101:30303?discport=30304", // IE +} + +// DiscoveryV5Bootnodes are the enode URLs of the P2P bootstrap nodes for the +// experimental RLPx v5 topic-discovery network. +var DiscoveryV5Bootnodes = []string{ + "enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30305", + "enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30308", + "enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30309", +} diff --git a/vendor/github.com/ethereum/go-ethereum/params/config.go b/vendor/github.com/ethereum/go-ethereum/params/config.go new file mode 100644 index 00000000..50268f63 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/params/config.go @@ -0,0 +1,318 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +var ( + // MainnetChainConfig is the chain parameters to run a node on the main network. + MainnetChainConfig = &ChainConfig{ + ChainId: MainNetChainID, + HomesteadBlock: MainNetHomesteadBlock, + DAOForkBlock: MainNetDAOForkBlock, + DAOForkSupport: true, + EIP150Block: MainNetHomesteadGasRepriceBlock, + EIP150Hash: MainNetHomesteadGasRepriceHash, + EIP155Block: MainNetSpuriousDragon, + EIP158Block: MainNetSpuriousDragon, + MetropolisBlock: MainNetMetropolisBlock, + + Ethash: new(EthashConfig), + } + + // TestnetChainConfig contains the chain parameters to run a node on the Ropsten test network. + TestnetChainConfig = &ChainConfig{ + ChainId: big.NewInt(3), + HomesteadBlock: big.NewInt(0), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(0), + EIP150Hash: common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"), + EIP155Block: big.NewInt(10), + EIP158Block: big.NewInt(10), + MetropolisBlock: TestNetMetropolisBlock, + + Ethash: new(EthashConfig), + } + + // RinkebyChainConfig contains the chain parameters to run a node on the Rinkeby test network. + RinkebyChainConfig = &ChainConfig{ + ChainId: big.NewInt(4), + HomesteadBlock: big.NewInt(1), + DAOForkBlock: nil, + DAOForkSupport: true, + EIP150Block: big.NewInt(2), + EIP150Hash: common.HexToHash("0x9b095b36c15eaf13044373aef8ee0bd3a382a5abb92e402afa44b8249c3a90e9"), + EIP155Block: big.NewInt(3), + EIP158Block: big.NewInt(3), + MetropolisBlock: TestNetMetropolisBlock, + + Clique: &CliqueConfig{ + Period: 15, + Epoch: 30000, + }, + } + + // AllProtocolChanges contains every protocol change (EIPs) + // introduced and accepted by the Ethereum core developers. + // + // This configuration is intentionally not using keyed fields. + // This configuration must *always* have all forks enabled, which + // means that all fields must be set at all times. This forces + // anyone adding flags to the config to also have to set these + // fields. + AllProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil} + TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil} + TestRules = TestChainConfig.Rules(new(big.Int)) +) + +// ChainConfig is the core config which determines the blockchain settings. +// +// ChainConfig is stored in the database on a per block basis. This means +// that any network, identified by its genesis block, can have its own +// set of configuration options. +type ChainConfig struct { + ChainId *big.Int `json:"chainId"` // Chain id identifies the current chain and is used for replay protection + + HomesteadBlock *big.Int `json:"homesteadBlock,omitempty"` // Homestead switch block (nil = no fork, 0 = already homestead) + DAOForkBlock *big.Int `json:"daoForkBlock,omitempty"` // TheDAO hard-fork switch block (nil = no fork) + DAOForkSupport bool `json:"daoForkSupport,omitempty"` // Whether the nodes supports or opposes the DAO hard-fork + + // EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150) + EIP150Block *big.Int `json:"eip150Block,omitempty"` // EIP150 HF block (nil = no fork) + EIP150Hash common.Hash `json:"eip150Hash,omitempty"` // EIP150 HF hash (fast sync aid) + + EIP155Block *big.Int `json:"eip155Block,omitempty"` // EIP155 HF block + EIP158Block *big.Int `json:"eip158Block,omitempty"` // EIP158 HF block + + MetropolisBlock *big.Int `json:"metropolisBlock,omitempty"` // Metropolis switch block (nil = no fork, 0 = alraedy on homestead) + + // Various consensus engines + Ethash *EthashConfig `json:"ethash,omitempty"` + Clique *CliqueConfig `json:"clique,omitempty"` +} + +// EthashConfig is the consensus engine configs for proof-of-work based sealing. +type EthashConfig struct{} + +// String implements the stringer interface, returning the consensus engine details. +func (c *EthashConfig) String() string { + return "ethash" +} + +// CliqueConfig is the consensus engine configs for proof-of-authority based sealing. +type CliqueConfig struct { + Period uint64 `json:"period"` // Number of seconds between blocks to enforce + Epoch uint64 `json:"epoch"` // Epoch length to reset votes and checkpoint +} + +// String implements the stringer interface, returning the consensus engine details. +func (c *CliqueConfig) String() string { + return "clique" +} + +// String implements the fmt.Stringer interface. +func (c *ChainConfig) String() string { + var engine interface{} + switch { + case c.Ethash != nil: + engine = c.Ethash + case c.Clique != nil: + engine = c.Clique + default: + engine = "unknown" + } + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Metropolis: %v Engine: %v}", + c.ChainId, + c.HomesteadBlock, + c.DAOForkBlock, + c.DAOForkSupport, + c.EIP150Block, + c.EIP155Block, + c.EIP158Block, + c.MetropolisBlock, + engine, + ) +} + +// IsHomestead returns whether num is either equal to the homestead block or greater. +func (c *ChainConfig) IsHomestead(num *big.Int) bool { + return isForked(c.HomesteadBlock, num) +} + +// IsDAO returns whether num is either equal to the DAO fork block or greater. +func (c *ChainConfig) IsDAOFork(num *big.Int) bool { + return isForked(c.DAOForkBlock, num) +} + +func (c *ChainConfig) IsEIP150(num *big.Int) bool { + return isForked(c.EIP150Block, num) +} + +func (c *ChainConfig) IsEIP155(num *big.Int) bool { + return isForked(c.EIP155Block, num) +} + +func (c *ChainConfig) IsEIP158(num *big.Int) bool { + return isForked(c.EIP158Block, num) +} + +func (c *ChainConfig) IsMetropolis(num *big.Int) bool { + return isForked(c.MetropolisBlock, num) +} + +// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice). +// +// The returned GasTable's fields shouldn't, under any circumstances, be changed. +func (c *ChainConfig) GasTable(num *big.Int) GasTable { + if num == nil { + return GasTableHomestead + } + switch { + case c.IsEIP158(num): + return GasTableEIP158 + case c.IsEIP150(num): + return GasTableHomesteadGasRepriceFork + default: + return GasTableHomestead + } +} + +// CheckCompatible checks whether scheduled fork transitions have been imported +// with a mismatching chain configuration. +func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError { + bhead := new(big.Int).SetUint64(height) + + // Iterate checkCompatible to find the lowest conflict. + var lasterr *ConfigCompatError + for { + err := c.checkCompatible(newcfg, bhead) + if err == nil || (lasterr != nil && err.RewindTo == lasterr.RewindTo) { + break + } + lasterr = err + bhead.SetUint64(err.RewindTo) + } + return lasterr +} + +func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *ConfigCompatError { + if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) { + return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock) + } + if isForkIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, head) { + return newCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock) + } + if c.IsDAOFork(head) && c.DAOForkSupport != newcfg.DAOForkSupport { + return newCompatError("DAO fork support flag", c.DAOForkBlock, newcfg.DAOForkBlock) + } + if isForkIncompatible(c.EIP150Block, newcfg.EIP150Block, head) { + return newCompatError("EIP150 fork block", c.EIP150Block, newcfg.EIP150Block) + } + if isForkIncompatible(c.EIP155Block, newcfg.EIP155Block, head) { + return newCompatError("EIP155 fork block", c.EIP155Block, newcfg.EIP155Block) + } + if isForkIncompatible(c.EIP158Block, newcfg.EIP158Block, head) { + return newCompatError("EIP158 fork block", c.EIP158Block, newcfg.EIP158Block) + } + if c.IsEIP158(head) && !configNumEqual(c.ChainId, newcfg.ChainId) { + return newCompatError("EIP158 chain ID", c.EIP158Block, newcfg.EIP158Block) + } + if isForkIncompatible(c.MetropolisBlock, newcfg.MetropolisBlock, head) { + return newCompatError("Metropolis fork block", c.MetropolisBlock, newcfg.MetropolisBlock) + } + return nil +} + +// isForkIncompatible returns true if a fork scheduled at s1 cannot be rescheduled to +// block s2 because head is already past the fork. +func isForkIncompatible(s1, s2, head *big.Int) bool { + return (isForked(s1, head) || isForked(s2, head)) && !configNumEqual(s1, s2) +} + +// isForked returns whether a fork scheduled at block s is active at the given head block. +func isForked(s, head *big.Int) bool { + if s == nil || head == nil { + return false + } + return s.Cmp(head) <= 0 +} + +func configNumEqual(x, y *big.Int) bool { + if x == nil { + return y == nil + } + if y == nil { + return x == nil + } + return x.Cmp(y) == 0 +} + +// ConfigCompatError is raised if the locally-stored blockchain is initialised with a +// ChainConfig that would alter the past. +type ConfigCompatError struct { + What string + // block numbers of the stored and new configurations + StoredConfig, NewConfig *big.Int + // the block number to which the local chain must be rewound to correct the error + RewindTo uint64 +} + +func newCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError { + var rew *big.Int + switch { + case storedblock == nil: + rew = newblock + case newblock == nil || storedblock.Cmp(newblock) < 0: + rew = storedblock + default: + rew = newblock + } + err := &ConfigCompatError{what, storedblock, newblock, 0} + if rew != nil && rew.Sign() > 0 { + err.RewindTo = rew.Uint64() - 1 + } + return err +} + +func (err *ConfigCompatError) Error() string { + return fmt.Sprintf("mismatching %s in database (have %d, want %d, rewindto %d)", err.What, err.StoredConfig, err.NewConfig, err.RewindTo) +} + +// Rules wraps ChainConfig and is merely syntatic sugar or can be used for functions +// that do not have or require information about the block. +// +// Rules is a one time interface meaning that it shouldn't be used in between transition +// phases. +type Rules struct { + ChainId *big.Int + IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool + IsMetropolis bool +} + +func (c *ChainConfig) Rules(num *big.Int) Rules { + chainId := c.ChainId + if chainId == nil { + chainId = new(big.Int) + } + return Rules{ChainId: new(big.Int).Set(chainId), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num), IsMetropolis: c.IsMetropolis(num)} +} diff --git a/vendor/github.com/ethereum/go-ethereum/params/dao.go b/vendor/github.com/ethereum/go-ethereum/params/dao.go new file mode 100644 index 00000000..ef8e838f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/params/dao.go @@ -0,0 +1,167 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +// TestNetDAOForkBlock is the block number where the DAO hard-fork commences on +// the Ethereum test network. It's enforced nil since it was decided not to do a +// testnet transition. +var TestNetDAOForkBlock *big.Int + +// MainNetDAOForkBlock is the block number where the DAO hard-fork commences on +// the Ethereum main network. +var MainNetDAOForkBlock = big.NewInt(1920000) + +// DAOForkBlockExtra is the block header extra-data field to set for the DAO fork +// point and a number of consecutive blocks to allow fast/light syncers to correctly +// pick the side they want ("dao-hard-fork"). +var DAOForkBlockExtra = common.FromHex("0x64616f2d686172642d666f726b") + +// DAOForkExtraRange is the number of consecutive blocks from the DAO fork point +// to override the extra-data in to prevent no-fork attacks. +var DAOForkExtraRange = big.NewInt(10) + +// DAORefundContract is the address of the refund contract to send DAO balances to. +var DAORefundContract = common.HexToAddress("0xbf4ed7b27f1d666546e30d74d50d173d20bca754") + +// DAODrainList is the list of accounts whose full balances will be moved into a +// refund contract at the beginning of the dao-fork block. +func DAODrainList() []common.Address { + return []common.Address{ + common.HexToAddress("0xd4fe7bc31cedb7bfb8a345f31e668033056b2728"), + common.HexToAddress("0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425"), + common.HexToAddress("0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f"), + common.HexToAddress("0xecd135fa4f61a655311e86238c92adcd779555d2"), + common.HexToAddress("0x1975bd06d486162d5dc297798dfc41edd5d160a7"), + common.HexToAddress("0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6"), + common.HexToAddress("0x319f70bab6845585f412ec7724b744fec6095c85"), + common.HexToAddress("0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936"), + common.HexToAddress("0x5c8536898fbb74fc7445814902fd08422eac56d0"), + common.HexToAddress("0x6966ab0d485353095148a2155858910e0965b6f9"), + common.HexToAddress("0x779543a0491a837ca36ce8c635d6154e3c4911a6"), + common.HexToAddress("0x2a5ed960395e2a49b1c758cef4aa15213cfd874c"), + common.HexToAddress("0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5"), + common.HexToAddress("0x9c50426be05db97f5d64fc54bf89eff947f0a321"), + common.HexToAddress("0x200450f06520bdd6c527622a273333384d870efb"), + common.HexToAddress("0xbe8539bfe837b67d1282b2b1d61c3f723966f049"), + common.HexToAddress("0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb"), + common.HexToAddress("0xf1385fb24aad0cd7432824085e42aff90886fef5"), + common.HexToAddress("0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091"), + common.HexToAddress("0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd"), + common.HexToAddress("0x51e0ddd9998364a2eb38588679f0d2c42653e4a6"), + common.HexToAddress("0x627a0a960c079c21c34f7612d5d230e01b4ad4c7"), + common.HexToAddress("0xf0b1aa0eb660754448a7937c022e30aa692fe0c5"), + common.HexToAddress("0x24c4d950dfd4dd1902bbed3508144a54542bba94"), + common.HexToAddress("0x9f27daea7aca0aa0446220b98d028715e3bc803d"), + common.HexToAddress("0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90"), + common.HexToAddress("0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b"), + common.HexToAddress("0x63ed5a272de2f6d968408b4acb9024f4cc208ebf"), + common.HexToAddress("0x6f6704e5a10332af6672e50b3d9754dc460dfa4d"), + common.HexToAddress("0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6"), + common.HexToAddress("0x492ea3bb0f3315521c31f273e565b868fc090f17"), + common.HexToAddress("0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00"), + common.HexToAddress("0x9ea779f907f0b315b364b0cfc39a0fde5b02a416"), + common.HexToAddress("0xceaeb481747ca6c540a000c1f3641f8cef161fa7"), + common.HexToAddress("0xcc34673c6c40e791051898567a1222daf90be287"), + common.HexToAddress("0x579a80d909f346fbfb1189493f521d7f48d52238"), + common.HexToAddress("0xe308bd1ac5fda103967359b2712dd89deffb7973"), + common.HexToAddress("0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c"), + common.HexToAddress("0xac1ecab32727358dba8962a0f3b261731aad9723"), + common.HexToAddress("0x4fd6ace747f06ece9c49699c7cabc62d02211f75"), + common.HexToAddress("0x440c59b325d2997a134c2c7c60a8c61611212bad"), + common.HexToAddress("0x4486a3d68fac6967006d7a517b889fd3f98c102b"), + common.HexToAddress("0x9c15b54878ba618f494b38f0ae7443db6af648ba"), + common.HexToAddress("0x27b137a85656544b1ccb5a0f2e561a5703c6a68f"), + common.HexToAddress("0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241"), + common.HexToAddress("0x23b75c2f6791eef49c69684db4c6c1f93bf49a50"), + common.HexToAddress("0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b"), + common.HexToAddress("0xb9637156d330c0d605a791f1c31ba5890582fe1c"), + common.HexToAddress("0x6131c42fa982e56929107413a9d526fd99405560"), + common.HexToAddress("0x1591fc0f688c81fbeb17f5426a162a7024d430c2"), + common.HexToAddress("0x542a9515200d14b68e934e9830d91645a980dd7a"), + common.HexToAddress("0xc4bbd073882dd2add2424cf47d35213405b01324"), + common.HexToAddress("0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4"), + common.HexToAddress("0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb"), + common.HexToAddress("0x3ba4d81db016dc2890c81f3acec2454bff5aada5"), + common.HexToAddress("0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab"), + common.HexToAddress("0xe4ae1efdfc53b73893af49113d8694a057b9c0d1"), + common.HexToAddress("0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5"), + common.HexToAddress("0x0737a6b837f97f46ebade41b9bc3e1c509c85c53"), + common.HexToAddress("0x97f43a37f595ab5dd318fb46e7a155eae057317a"), + common.HexToAddress("0x52c5317c848ba20c7504cb2c8052abd1fde29d03"), + common.HexToAddress("0x4863226780fe7c0356454236d3b1c8792785748d"), + common.HexToAddress("0x5d2b2e6fcbe3b11d26b525e085ff818dae332479"), + common.HexToAddress("0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c"), + common.HexToAddress("0x057b56736d32b86616a10f619859c6cd6f59092a"), + common.HexToAddress("0x9aa008f65de0b923a2a4f02012ad034a5e2e2192"), + common.HexToAddress("0x304a554a310c7e546dfe434669c62820b7d83490"), + common.HexToAddress("0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79"), + common.HexToAddress("0x4deb0033bb26bc534b197e61d19e0733e5679784"), + common.HexToAddress("0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a"), + common.HexToAddress("0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b"), + common.HexToAddress("0x4fa802324e929786dbda3b8820dc7834e9134a2a"), + common.HexToAddress("0x9da397b9e80755301a3b32173283a91c0ef6c87e"), + common.HexToAddress("0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6"), + common.HexToAddress("0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9"), + common.HexToAddress("0x5dc28b15dffed94048d73806ce4b7a4612a1d48f"), + common.HexToAddress("0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76"), + common.HexToAddress("0x12e626b0eebfe86a56d633b9864e389b45dcb260"), + common.HexToAddress("0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7"), + common.HexToAddress("0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5"), + common.HexToAddress("0xd164b088bd9108b60d0ca3751da4bceb207b0782"), + common.HexToAddress("0x6231b6d0d5e77fe001c2a460bd9584fee60d409b"), + common.HexToAddress("0x1cba23d343a983e9b5cfd19496b9a9701ada385f"), + common.HexToAddress("0xa82f360a8d3455c5c41366975bde739c37bfeb8a"), + common.HexToAddress("0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339"), + common.HexToAddress("0x005f5cee7a43331d5a3d3eec71305925a62f34b6"), + common.HexToAddress("0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d"), + common.HexToAddress("0xd131637d5275fd1a68a3200f4ad25c71a2a9522e"), + common.HexToAddress("0xbc07118b9ac290e4622f5e77a0853539789effbe"), + common.HexToAddress("0x47e7aa56d6bdf3f36be34619660de61275420af8"), + common.HexToAddress("0xacd87e28b0c9d1254e868b81cba4cc20d9a32225"), + common.HexToAddress("0xadf80daec7ba8dcf15392f1ac611fff65d94f880"), + common.HexToAddress("0x5524c55fb03cf21f549444ccbecb664d0acad706"), + common.HexToAddress("0x40b803a9abce16f50f36a77ba41180eb90023925"), + common.HexToAddress("0xfe24cdd8648121a43a7c86d289be4dd2951ed49f"), + common.HexToAddress("0x17802f43a0137c506ba92291391a8a8f207f487d"), + common.HexToAddress("0x253488078a4edf4d6f42f113d1e62836a942cf1a"), + common.HexToAddress("0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915"), + common.HexToAddress("0xb136707642a4ea12fb4bae820f03d2562ebff487"), + common.HexToAddress("0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940"), + common.HexToAddress("0xf14c14075d6c4ed84b86798af0956deef67365b5"), + common.HexToAddress("0xca544e5c4687d109611d0f8f928b53a25af72448"), + common.HexToAddress("0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c"), + common.HexToAddress("0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7"), + common.HexToAddress("0x6d87578288b6cb5549d5076a207456a1f6a63dc0"), + common.HexToAddress("0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e"), + common.HexToAddress("0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6"), + common.HexToAddress("0x2b3455ec7fedf16e646268bf88846bd7a2319bb2"), + common.HexToAddress("0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a"), + common.HexToAddress("0xd343b217de44030afaa275f54d31a9317c7f441e"), + common.HexToAddress("0x84ef4b2357079cd7a7c69fd7a37cd0609a679106"), + common.HexToAddress("0xda2fef9e4a3230988ff17df2165440f37e8b1708"), + common.HexToAddress("0xf4c64518ea10f995918a454158c6b61407ea345c"), + common.HexToAddress("0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97"), + common.HexToAddress("0xbb9bc244d798123fde783fcc1c72d3bb8c189413"), + common.HexToAddress("0x807640a13483f8ac783c557fcdf27be11ea4ac7a"), + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/params/denomination.go b/vendor/github.com/ethereum/go-ethereum/params/denomination.go new file mode 100644 index 00000000..9e1b5250 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/params/denomination.go @@ -0,0 +1,34 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +const ( + // These are the multipliers for ether denominations. + // Example: To get the wei value of an amount in 'douglas', use + // + // new(big.Int).Mul(value, big.NewInt(params.Douglas)) + // + Wei = 1 + Ada = 1e3 + Babbage = 1e6 + Shannon = 1e9 + Szabo = 1e12 + Finney = 1e15 + Ether = 1e18 + Einstein = 1e21 + Douglas = 1e42 +) diff --git a/vendor/github.com/ethereum/go-ethereum/params/gas_table.go b/vendor/github.com/ethereum/go-ethereum/params/gas_table.go new file mode 100644 index 00000000..a0605390 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/params/gas_table.go @@ -0,0 +1,77 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +type GasTable struct { + ExtcodeSize uint64 + ExtcodeCopy uint64 + Balance uint64 + SLoad uint64 + Calls uint64 + Suicide uint64 + + ExpByte uint64 + + // CreateBySuicide occurs when the + // refunded account is one that does + // not exist. This logic is similar + // to call. May be left nil. Nil means + // not charged. + CreateBySuicide uint64 +} + +var ( + // GasTableHomestead contain the gas prices for + // the homestead phase. + GasTableHomestead = GasTable{ + ExtcodeSize: 20, + ExtcodeCopy: 20, + Balance: 20, + SLoad: 50, + Calls: 40, + Suicide: 0, + ExpByte: 10, + } + + // GasTableHomestead contain the gas re-prices for + // the homestead phase. + // + // TODO rename to GasTableEIP150 + GasTableHomesteadGasRepriceFork = GasTable{ + ExtcodeSize: 700, + ExtcodeCopy: 700, + Balance: 400, + SLoad: 200, + Calls: 700, + Suicide: 5000, + ExpByte: 10, + + CreateBySuicide: 25000, + } + + GasTableEIP158 = GasTable{ + ExtcodeSize: 700, + ExtcodeCopy: 700, + Balance: 400, + SLoad: 200, + Calls: 700, + Suicide: 5000, + ExpByte: 50, + + CreateBySuicide: 25000, + } +) diff --git a/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go b/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go new file mode 100644 index 00000000..f48bf499 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/params/protocol_params.go @@ -0,0 +1,75 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +import "math/big" + +const ( + MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. + ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction. + SloadGas uint64 = 50 // Multiplied by the number of 32-byte words that are copied (round up) for any *COPY operation and added. + CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero. + CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior. + TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions. + TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions. + TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions. + QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation. + SstoreSetGas uint64 = 20000 // Once per SLOAD operation. + LogDataGas uint64 = 8 // Per byte in a LOG* operation's data. + CallStipend uint64 = 2300 // Free gas given at beginning of call. + EcrecoverGas uint64 = 3000 // + Sha256WordGas uint64 = 12 // + + Sha3Gas uint64 = 30 // Once per SHA3 operation. + Sha256Gas uint64 = 60 // + IdentityWordGas uint64 = 3 // + Sha3WordGas uint64 = 6 // Once per word of the SHA3 operation's data. + SstoreResetGas uint64 = 5000 // Once per SSTORE operation if the zeroness changes from zero. + SstoreClearGas uint64 = 5000 // Once per SSTORE operation if the zeroness doesn't change. + SstoreRefundGas uint64 = 15000 // Once per SSTORE operation if the zeroness changes to zero. + JumpdestGas uint64 = 1 // Refunded gas, once per SSTORE operation if the zeroness changes to zero. + IdentityGas uint64 = 15 // + EpochDuration uint64 = 30000 // Duration between proof-of-work epochs. + CallGas uint64 = 40 // Once per CALL operation & message call transaction. + CreateDataGas uint64 = 200 // + Ripemd160Gas uint64 = 600 // + Ripemd160WordGas uint64 = 120 // + CallCreateDepth uint64 = 1024 // Maximum depth of call/create stack. + ExpGas uint64 = 10 // Once per EXP instruction + LogGas uint64 = 375 // Per LOG* operation. + CopyGas uint64 = 3 // + StackLimit uint64 = 1024 // Maximum size of VM stack allowed. + TierStepGas uint64 = 0 // Once per operation, for a selection of them. + LogTopicGas uint64 = 375 // Multiplied by the * of the LOG*, per LOG transaction. e.g. LOG0 incurs 0 * c_txLogTopicGas, LOG4 incurs 4 * c_txLogTopicGas. + CreateGas uint64 = 32000 // Once per CREATE operation & contract-creation transaction. + SuicideRefundGas uint64 = 24000 // Refunded following a suicide operation. + MemoryGas uint64 = 3 // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. + TxDataNonZeroGas uint64 = 68 // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. + + MaxCodeSize = 24576 +) + +var ( + GasLimitBoundDivisor = big.NewInt(1024) // The bound divisor of the gas limit, used in update calculations. + MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be. + GenesisGasLimit = big.NewInt(4712388) // Gas limit of the Genesis block. + TargetGasLimit = new(big.Int).Set(GenesisGasLimit) // The artificial target + DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations. + GenesisDifficulty = big.NewInt(131072) // Difficulty of the Genesis block. + MinimumDifficulty = big.NewInt(131072) // The minimum that the difficulty may ever be. + DurationLimit = big.NewInt(13) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. +) diff --git a/vendor/github.com/ethereum/go-ethereum/params/util.go b/vendor/github.com/ethereum/go-ethereum/params/util.go new file mode 100644 index 00000000..d4d43d04 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/params/util.go @@ -0,0 +1,47 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +import ( + "math" + "math/big" + + "github.com/ethereum/go-ethereum/common" +) + +var ( + TestNetGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") // Testnet genesis hash to enforce below configs on + MainNetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3") // Mainnet genesis hash to enforce below configs on + + TestNetHomesteadBlock = big.NewInt(0) // Testnet homestead block + MainNetHomesteadBlock = big.NewInt(1150000) // Mainnet homestead block + + TestNetHomesteadGasRepriceBlock = big.NewInt(0) // Testnet gas reprice block + MainNetHomesteadGasRepriceBlock = big.NewInt(2463000) // Mainnet gas reprice block + + TestNetHomesteadGasRepriceHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d") // Testnet gas reprice block hash (used by fast sync) + MainNetHomesteadGasRepriceHash = common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0") // Mainnet gas reprice block hash (used by fast sync) + + TestNetSpuriousDragon = big.NewInt(10) + MainNetSpuriousDragon = big.NewInt(2675000) + + TestNetMetropolisBlock = big.NewInt(math.MaxInt64) + MainNetMetropolisBlock = big.NewInt(math.MaxInt64) + + TestNetChainID = big.NewInt(3) // Test net default chain ID + MainNetChainID = big.NewInt(1) // main net default chain ID +) diff --git a/vendor/github.com/ethereum/go-ethereum/params/version.go b/vendor/github.com/ethereum/go-ethereum/params/version.go new file mode 100644 index 00000000..fbf49ead --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/params/version.go @@ -0,0 +1,45 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package params + +import ( + "fmt" +) + +const ( + VersionMajor = 1 // Major version component of the current release + VersionMinor = 6 // Minor version component of the current release + VersionPatch = 6 // Patch version component of the current release + VersionMeta = "unstable" // Version metadata to append to the version string +) + +// Version holds the textual version string. +var Version = func() string { + v := fmt.Sprintf("%d.%d.%d", VersionMajor, VersionMinor, VersionPatch) + if VersionMeta != "" { + v += "-" + VersionMeta + } + return v +}() + +func VersionWithCommit(gitCommit string) string { + vsn := Version + if len(gitCommit) >= 8 { + vsn += "-" + gitCommit[:8] + } + return vsn +} diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/decode.go b/vendor/github.com/ethereum/go-ethereum/rlp/decode.go new file mode 100644 index 00000000..78ccf627 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rlp/decode.go @@ -0,0 +1,1041 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rlp + +import ( + "bufio" + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + "reflect" + "strings" +) + +var ( + errNoPointer = errors.New("rlp: interface given to Decode must be a pointer") + errDecodeIntoNil = errors.New("rlp: pointer given to Decode must not be nil") +) + +// Decoder is implemented by types that require custom RLP +// decoding rules or need to decode into private fields. +// +// The DecodeRLP method should read one value from the given +// Stream. It is not forbidden to read less or more, but it might +// be confusing. +type Decoder interface { + DecodeRLP(*Stream) error +} + +// Decode parses RLP-encoded data from r and stores the result in the +// value pointed to by val. Val must be a non-nil pointer. If r does +// not implement ByteReader, Decode will do its own buffering. +// +// Decode uses the following type-dependent decoding rules: +// +// If the type implements the Decoder interface, decode calls +// DecodeRLP. +// +// To decode into a pointer, Decode will decode into the value pointed +// to. If the pointer is nil, a new value of the pointer's element +// type is allocated. If the pointer is non-nil, the existing value +// will be reused. +// +// To decode into a struct, Decode expects the input to be an RLP +// list. The decoded elements of the list are assigned to each public +// field in the order given by the struct's definition. The input list +// must contain an element for each decoded field. Decode returns an +// error if there are too few or too many elements. +// +// The decoding of struct fields honours certain struct tags, "tail", +// "nil" and "-". +// +// The "-" tag ignores fields. +// +// For an explanation of "tail", see the example. +// +// The "nil" tag applies to pointer-typed fields and changes the decoding +// rules for the field such that input values of size zero decode as a nil +// pointer. This tag can be useful when decoding recursive types. +// +// type StructWithEmptyOK struct { +// Foo *[20]byte `rlp:"nil"` +// } +// +// To decode into a slice, the input must be a list and the resulting +// slice will contain the input elements in order. For byte slices, +// the input must be an RLP string. Array types decode similarly, with +// the additional restriction that the number of input elements (or +// bytes) must match the array's length. +// +// To decode into a Go string, the input must be an RLP string. The +// input bytes are taken as-is and will not necessarily be valid UTF-8. +// +// To decode into an unsigned integer type, the input must also be an RLP +// string. The bytes are interpreted as a big endian representation of +// the integer. If the RLP string is larger than the bit size of the +// type, Decode will return an error. Decode also supports *big.Int. +// There is no size limit for big integers. +// +// To decode into an interface value, Decode stores one of these +// in the value: +// +// []interface{}, for RLP lists +// []byte, for RLP strings +// +// Non-empty interface types are not supported, nor are booleans, +// signed integers, floating point numbers, maps, channels and +// functions. +// +// Note that Decode does not set an input limit for all readers +// and may be vulnerable to panics cause by huge value sizes. If +// you need an input limit, use +// +// NewStream(r, limit).Decode(val) +func Decode(r io.Reader, val interface{}) error { + // TODO: this could use a Stream from a pool. + return NewStream(r, 0).Decode(val) +} + +// DecodeBytes parses RLP data from b into val. +// Please see the documentation of Decode for the decoding rules. +// The input must contain exactly one value and no trailing data. +func DecodeBytes(b []byte, val interface{}) error { + // TODO: this could use a Stream from a pool. + r := bytes.NewReader(b) + if err := NewStream(r, uint64(len(b))).Decode(val); err != nil { + return err + } + if r.Len() > 0 { + return ErrMoreThanOneValue + } + return nil +} + +type decodeError struct { + msg string + typ reflect.Type + ctx []string +} + +func (err *decodeError) Error() string { + ctx := "" + if len(err.ctx) > 0 { + ctx = ", decoding into " + for i := len(err.ctx) - 1; i >= 0; i-- { + ctx += err.ctx[i] + } + } + return fmt.Sprintf("rlp: %s for %v%s", err.msg, err.typ, ctx) +} + +func wrapStreamError(err error, typ reflect.Type) error { + switch err { + case ErrCanonInt: + return &decodeError{msg: "non-canonical integer (leading zero bytes)", typ: typ} + case ErrCanonSize: + return &decodeError{msg: "non-canonical size information", typ: typ} + case ErrExpectedList: + return &decodeError{msg: "expected input list", typ: typ} + case ErrExpectedString: + return &decodeError{msg: "expected input string or byte", typ: typ} + case errUintOverflow: + return &decodeError{msg: "input string too long", typ: typ} + case errNotAtEOL: + return &decodeError{msg: "input list has too many elements", typ: typ} + } + return err +} + +func addErrorContext(err error, ctx string) error { + if decErr, ok := err.(*decodeError); ok { + decErr.ctx = append(decErr.ctx, ctx) + } + return err +} + +var ( + decoderInterface = reflect.TypeOf(new(Decoder)).Elem() + bigInt = reflect.TypeOf(big.Int{}) +) + +func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) { + kind := typ.Kind() + switch { + case typ == rawValueType: + return decodeRawValue, nil + case typ.Implements(decoderInterface): + return decodeDecoder, nil + case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderInterface): + return decodeDecoderNoPtr, nil + case typ.AssignableTo(reflect.PtrTo(bigInt)): + return decodeBigInt, nil + case typ.AssignableTo(bigInt): + return decodeBigIntNoPtr, nil + case isUint(kind): + return decodeUint, nil + case kind == reflect.Bool: + return decodeBool, nil + case kind == reflect.String: + return decodeString, nil + case kind == reflect.Slice || kind == reflect.Array: + return makeListDecoder(typ, tags) + case kind == reflect.Struct: + return makeStructDecoder(typ) + case kind == reflect.Ptr: + if tags.nilOK { + return makeOptionalPtrDecoder(typ) + } + return makePtrDecoder(typ) + case kind == reflect.Interface: + return decodeInterface, nil + default: + return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ) + } +} + +func decodeRawValue(s *Stream, val reflect.Value) error { + r, err := s.Raw() + if err != nil { + return err + } + val.SetBytes(r) + return nil +} + +func decodeUint(s *Stream, val reflect.Value) error { + typ := val.Type() + num, err := s.uint(typ.Bits()) + if err != nil { + return wrapStreamError(err, val.Type()) + } + val.SetUint(num) + return nil +} + +func decodeBool(s *Stream, val reflect.Value) error { + b, err := s.Bool() + if err != nil { + return wrapStreamError(err, val.Type()) + } + val.SetBool(b) + return nil +} + +func decodeString(s *Stream, val reflect.Value) error { + b, err := s.Bytes() + if err != nil { + return wrapStreamError(err, val.Type()) + } + val.SetString(string(b)) + return nil +} + +func decodeBigIntNoPtr(s *Stream, val reflect.Value) error { + return decodeBigInt(s, val.Addr()) +} + +func decodeBigInt(s *Stream, val reflect.Value) error { + b, err := s.Bytes() + if err != nil { + return wrapStreamError(err, val.Type()) + } + i := val.Interface().(*big.Int) + if i == nil { + i = new(big.Int) + val.Set(reflect.ValueOf(i)) + } + // Reject leading zero bytes + if len(b) > 0 && b[0] == 0 { + return wrapStreamError(ErrCanonInt, val.Type()) + } + i.SetBytes(b) + return nil +} + +func makeListDecoder(typ reflect.Type, tag tags) (decoder, error) { + etype := typ.Elem() + if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) { + if typ.Kind() == reflect.Array { + return decodeByteArray, nil + } else { + return decodeByteSlice, nil + } + } + etypeinfo, err := cachedTypeInfo1(etype, tags{}) + if err != nil { + return nil, err + } + var dec decoder + switch { + case typ.Kind() == reflect.Array: + dec = func(s *Stream, val reflect.Value) error { + return decodeListArray(s, val, etypeinfo.decoder) + } + case tag.tail: + // A slice with "tail" tag can occur as the last field + // of a struct and is supposed to swallow all remaining + // list elements. The struct decoder already called s.List, + // proceed directly to decoding the elements. + dec = func(s *Stream, val reflect.Value) error { + return decodeSliceElems(s, val, etypeinfo.decoder) + } + default: + dec = func(s *Stream, val reflect.Value) error { + return decodeListSlice(s, val, etypeinfo.decoder) + } + } + return dec, nil +} + +func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error { + size, err := s.List() + if err != nil { + return wrapStreamError(err, val.Type()) + } + if size == 0 { + val.Set(reflect.MakeSlice(val.Type(), 0, 0)) + return s.ListEnd() + } + if err := decodeSliceElems(s, val, elemdec); err != nil { + return err + } + return s.ListEnd() +} + +func decodeSliceElems(s *Stream, val reflect.Value, elemdec decoder) error { + i := 0 + for ; ; i++ { + // grow slice if necessary + if i >= val.Cap() { + newcap := val.Cap() + val.Cap()/2 + if newcap < 4 { + newcap = 4 + } + newv := reflect.MakeSlice(val.Type(), val.Len(), newcap) + reflect.Copy(newv, val) + val.Set(newv) + } + if i >= val.Len() { + val.SetLen(i + 1) + } + // decode into element + if err := elemdec(s, val.Index(i)); err == EOL { + break + } else if err != nil { + return addErrorContext(err, fmt.Sprint("[", i, "]")) + } + } + if i < val.Len() { + val.SetLen(i) + } + return nil +} + +func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error { + if _, err := s.List(); err != nil { + return wrapStreamError(err, val.Type()) + } + vlen := val.Len() + i := 0 + for ; i < vlen; i++ { + if err := elemdec(s, val.Index(i)); err == EOL { + break + } else if err != nil { + return addErrorContext(err, fmt.Sprint("[", i, "]")) + } + } + if i < vlen { + return &decodeError{msg: "input list has too few elements", typ: val.Type()} + } + return wrapStreamError(s.ListEnd(), val.Type()) +} + +func decodeByteSlice(s *Stream, val reflect.Value) error { + b, err := s.Bytes() + if err != nil { + return wrapStreamError(err, val.Type()) + } + val.SetBytes(b) + return nil +} + +func decodeByteArray(s *Stream, val reflect.Value) error { + kind, size, err := s.Kind() + if err != nil { + return err + } + vlen := val.Len() + switch kind { + case Byte: + if vlen == 0 { + return &decodeError{msg: "input string too long", typ: val.Type()} + } + if vlen > 1 { + return &decodeError{msg: "input string too short", typ: val.Type()} + } + bv, _ := s.Uint() + val.Index(0).SetUint(bv) + case String: + if uint64(vlen) < size { + return &decodeError{msg: "input string too long", typ: val.Type()} + } + if uint64(vlen) > size { + return &decodeError{msg: "input string too short", typ: val.Type()} + } + slice := val.Slice(0, vlen).Interface().([]byte) + if err := s.readFull(slice); err != nil { + return err + } + // Reject cases where single byte encoding should have been used. + if size == 1 && slice[0] < 128 { + return wrapStreamError(ErrCanonSize, val.Type()) + } + case List: + return wrapStreamError(ErrExpectedString, val.Type()) + } + return nil +} + +func makeStructDecoder(typ reflect.Type) (decoder, error) { + fields, err := structFields(typ) + if err != nil { + return nil, err + } + dec := func(s *Stream, val reflect.Value) (err error) { + if _, err := s.List(); err != nil { + return wrapStreamError(err, typ) + } + for _, f := range fields { + err := f.info.decoder(s, val.Field(f.index)) + if err == EOL { + return &decodeError{msg: "too few elements", typ: typ} + } else if err != nil { + return addErrorContext(err, "."+typ.Field(f.index).Name) + } + } + return wrapStreamError(s.ListEnd(), typ) + } + return dec, nil +} + +// makePtrDecoder creates a decoder that decodes into +// the pointer's element type. +func makePtrDecoder(typ reflect.Type) (decoder, error) { + etype := typ.Elem() + etypeinfo, err := cachedTypeInfo1(etype, tags{}) + if err != nil { + return nil, err + } + dec := func(s *Stream, val reflect.Value) (err error) { + newval := val + if val.IsNil() { + newval = reflect.New(etype) + } + if err = etypeinfo.decoder(s, newval.Elem()); err == nil { + val.Set(newval) + } + return err + } + return dec, nil +} + +// makeOptionalPtrDecoder creates a decoder that decodes empty values +// as nil. Non-empty values are decoded into a value of the element type, +// just like makePtrDecoder does. +// +// This decoder is used for pointer-typed struct fields with struct tag "nil". +func makeOptionalPtrDecoder(typ reflect.Type) (decoder, error) { + etype := typ.Elem() + etypeinfo, err := cachedTypeInfo1(etype, tags{}) + if err != nil { + return nil, err + } + dec := func(s *Stream, val reflect.Value) (err error) { + kind, size, err := s.Kind() + if err != nil || size == 0 && kind != Byte { + // rearm s.Kind. This is important because the input + // position must advance to the next value even though + // we don't read anything. + s.kind = -1 + // set the pointer to nil. + val.Set(reflect.Zero(typ)) + return err + } + newval := val + if val.IsNil() { + newval = reflect.New(etype) + } + if err = etypeinfo.decoder(s, newval.Elem()); err == nil { + val.Set(newval) + } + return err + } + return dec, nil +} + +var ifsliceType = reflect.TypeOf([]interface{}{}) + +func decodeInterface(s *Stream, val reflect.Value) error { + if val.Type().NumMethod() != 0 { + return fmt.Errorf("rlp: type %v is not RLP-serializable", val.Type()) + } + kind, _, err := s.Kind() + if err != nil { + return err + } + if kind == List { + slice := reflect.New(ifsliceType).Elem() + if err := decodeListSlice(s, slice, decodeInterface); err != nil { + return err + } + val.Set(slice) + } else { + b, err := s.Bytes() + if err != nil { + return err + } + val.Set(reflect.ValueOf(b)) + } + return nil +} + +// This decoder is used for non-pointer values of types +// that implement the Decoder interface using a pointer receiver. +func decodeDecoderNoPtr(s *Stream, val reflect.Value) error { + return val.Addr().Interface().(Decoder).DecodeRLP(s) +} + +func decodeDecoder(s *Stream, val reflect.Value) error { + // Decoder instances are not handled using the pointer rule if the type + // implements Decoder with pointer receiver (i.e. always) + // because it might handle empty values specially. + // We need to allocate one here in this case, like makePtrDecoder does. + if val.Kind() == reflect.Ptr && val.IsNil() { + val.Set(reflect.New(val.Type().Elem())) + } + return val.Interface().(Decoder).DecodeRLP(s) +} + +// Kind represents the kind of value contained in an RLP stream. +type Kind int + +const ( + Byte Kind = iota + String + List +) + +func (k Kind) String() string { + switch k { + case Byte: + return "Byte" + case String: + return "String" + case List: + return "List" + default: + return fmt.Sprintf("Unknown(%d)", k) + } +} + +var ( + // EOL is returned when the end of the current list + // has been reached during streaming. + EOL = errors.New("rlp: end of list") + + // Actual Errors + ErrExpectedString = errors.New("rlp: expected String or Byte") + ErrExpectedList = errors.New("rlp: expected List") + ErrCanonInt = errors.New("rlp: non-canonical integer format") + ErrCanonSize = errors.New("rlp: non-canonical size information") + ErrElemTooLarge = errors.New("rlp: element is larger than containing list") + ErrValueTooLarge = errors.New("rlp: value size exceeds available input length") + + // This error is reported by DecodeBytes if the slice contains + // additional data after the first RLP value. + ErrMoreThanOneValue = errors.New("rlp: input contains more than one value") + + // internal errors + errNotInList = errors.New("rlp: call of ListEnd outside of any list") + errNotAtEOL = errors.New("rlp: call of ListEnd not positioned at EOL") + errUintOverflow = errors.New("rlp: uint overflow") +) + +// ByteReader must be implemented by any input reader for a Stream. It +// is implemented by e.g. bufio.Reader and bytes.Reader. +type ByteReader interface { + io.Reader + io.ByteReader +} + +// Stream can be used for piecemeal decoding of an input stream. This +// is useful if the input is very large or if the decoding rules for a +// type depend on the input structure. Stream does not keep an +// internal buffer. After decoding a value, the input reader will be +// positioned just before the type information for the next value. +// +// When decoding a list and the input position reaches the declared +// length of the list, all operations will return error EOL. +// The end of the list must be acknowledged using ListEnd to continue +// reading the enclosing list. +// +// Stream is not safe for concurrent use. +type Stream struct { + r ByteReader + + // number of bytes remaining to be read from r. + remaining uint64 + limited bool + + // auxiliary buffer for integer decoding + uintbuf []byte + + kind Kind // kind of value ahead + size uint64 // size of value ahead + byteval byte // value of single byte in type tag + kinderr error // error from last readKind + stack []listpos +} + +type listpos struct{ pos, size uint64 } + +// NewStream creates a new decoding stream reading from r. +// +// If r implements the ByteReader interface, Stream will +// not introduce any buffering. +// +// For non-toplevel values, Stream returns ErrElemTooLarge +// for values that do not fit into the enclosing list. +// +// Stream supports an optional input limit. If a limit is set, the +// size of any toplevel value will be checked against the remaining +// input length. Stream operations that encounter a value exceeding +// the remaining input length will return ErrValueTooLarge. The limit +// can be set by passing a non-zero value for inputLimit. +// +// If r is a bytes.Reader or strings.Reader, the input limit is set to +// the length of r's underlying data unless an explicit limit is +// provided. +func NewStream(r io.Reader, inputLimit uint64) *Stream { + s := new(Stream) + s.Reset(r, inputLimit) + return s +} + +// NewListStream creates a new stream that pretends to be positioned +// at an encoded list of the given length. +func NewListStream(r io.Reader, len uint64) *Stream { + s := new(Stream) + s.Reset(r, len) + s.kind = List + s.size = len + return s +} + +// Bytes reads an RLP string and returns its contents as a byte slice. +// If the input does not contain an RLP string, the returned +// error will be ErrExpectedString. +func (s *Stream) Bytes() ([]byte, error) { + kind, size, err := s.Kind() + if err != nil { + return nil, err + } + switch kind { + case Byte: + s.kind = -1 // rearm Kind + return []byte{s.byteval}, nil + case String: + b := make([]byte, size) + if err = s.readFull(b); err != nil { + return nil, err + } + if size == 1 && b[0] < 128 { + return nil, ErrCanonSize + } + return b, nil + default: + return nil, ErrExpectedString + } +} + +// Raw reads a raw encoded value including RLP type information. +func (s *Stream) Raw() ([]byte, error) { + kind, size, err := s.Kind() + if err != nil { + return nil, err + } + if kind == Byte { + s.kind = -1 // rearm Kind + return []byte{s.byteval}, nil + } + // the original header has already been read and is no longer + // available. read content and put a new header in front of it. + start := headsize(size) + buf := make([]byte, uint64(start)+size) + if err := s.readFull(buf[start:]); err != nil { + return nil, err + } + if kind == String { + puthead(buf, 0x80, 0xB8, size) + } else { + puthead(buf, 0xC0, 0xF7, size) + } + return buf, nil +} + +// Uint reads an RLP string of up to 8 bytes and returns its contents +// as an unsigned integer. If the input does not contain an RLP string, the +// returned error will be ErrExpectedString. +func (s *Stream) Uint() (uint64, error) { + return s.uint(64) +} + +func (s *Stream) uint(maxbits int) (uint64, error) { + kind, size, err := s.Kind() + if err != nil { + return 0, err + } + switch kind { + case Byte: + if s.byteval == 0 { + return 0, ErrCanonInt + } + s.kind = -1 // rearm Kind + return uint64(s.byteval), nil + case String: + if size > uint64(maxbits/8) { + return 0, errUintOverflow + } + v, err := s.readUint(byte(size)) + switch { + case err == ErrCanonSize: + // Adjust error because we're not reading a size right now. + return 0, ErrCanonInt + case err != nil: + return 0, err + case size > 0 && v < 128: + return 0, ErrCanonSize + default: + return v, nil + } + default: + return 0, ErrExpectedString + } +} + +// Bool reads an RLP string of up to 1 byte and returns its contents +// as a boolean. If the input does not contain an RLP string, the +// returned error will be ErrExpectedString. +func (s *Stream) Bool() (bool, error) { + num, err := s.uint(8) + if err != nil { + return false, err + } + switch num { + case 0: + return false, nil + case 1: + return true, nil + default: + return false, fmt.Errorf("rlp: invalid boolean value: %d", num) + } +} + +// List starts decoding an RLP list. If the input does not contain a +// list, the returned error will be ErrExpectedList. When the list's +// end has been reached, any Stream operation will return EOL. +func (s *Stream) List() (size uint64, err error) { + kind, size, err := s.Kind() + if err != nil { + return 0, err + } + if kind != List { + return 0, ErrExpectedList + } + s.stack = append(s.stack, listpos{0, size}) + s.kind = -1 + s.size = 0 + return size, nil +} + +// ListEnd returns to the enclosing list. +// The input reader must be positioned at the end of a list. +func (s *Stream) ListEnd() error { + if len(s.stack) == 0 { + return errNotInList + } + tos := s.stack[len(s.stack)-1] + if tos.pos != tos.size { + return errNotAtEOL + } + s.stack = s.stack[:len(s.stack)-1] // pop + if len(s.stack) > 0 { + s.stack[len(s.stack)-1].pos += tos.size + } + s.kind = -1 + s.size = 0 + return nil +} + +// Decode decodes a value and stores the result in the value pointed +// to by val. Please see the documentation for the Decode function +// to learn about the decoding rules. +func (s *Stream) Decode(val interface{}) error { + if val == nil { + return errDecodeIntoNil + } + rval := reflect.ValueOf(val) + rtyp := rval.Type() + if rtyp.Kind() != reflect.Ptr { + return errNoPointer + } + if rval.IsNil() { + return errDecodeIntoNil + } + info, err := cachedTypeInfo(rtyp.Elem(), tags{}) + if err != nil { + return err + } + + err = info.decoder(s, rval.Elem()) + if decErr, ok := err.(*decodeError); ok && len(decErr.ctx) > 0 { + // add decode target type to error so context has more meaning + decErr.ctx = append(decErr.ctx, fmt.Sprint("(", rtyp.Elem(), ")")) + } + return err +} + +// Reset discards any information about the current decoding context +// and starts reading from r. This method is meant to facilitate reuse +// of a preallocated Stream across many decoding operations. +// +// If r does not also implement ByteReader, Stream will do its own +// buffering. +func (s *Stream) Reset(r io.Reader, inputLimit uint64) { + if inputLimit > 0 { + s.remaining = inputLimit + s.limited = true + } else { + // Attempt to automatically discover + // the limit when reading from a byte slice. + switch br := r.(type) { + case *bytes.Reader: + s.remaining = uint64(br.Len()) + s.limited = true + case *strings.Reader: + s.remaining = uint64(br.Len()) + s.limited = true + default: + s.limited = false + } + } + // Wrap r with a buffer if it doesn't have one. + bufr, ok := r.(ByteReader) + if !ok { + bufr = bufio.NewReader(r) + } + s.r = bufr + // Reset the decoding context. + s.stack = s.stack[:0] + s.size = 0 + s.kind = -1 + s.kinderr = nil + if s.uintbuf == nil { + s.uintbuf = make([]byte, 8) + } +} + +// Kind returns the kind and size of the next value in the +// input stream. +// +// The returned size is the number of bytes that make up the value. +// For kind == Byte, the size is zero because the value is +// contained in the type tag. +// +// The first call to Kind will read size information from the input +// reader and leave it positioned at the start of the actual bytes of +// the value. Subsequent calls to Kind (until the value is decoded) +// will not advance the input reader and return cached information. +func (s *Stream) Kind() (kind Kind, size uint64, err error) { + var tos *listpos + if len(s.stack) > 0 { + tos = &s.stack[len(s.stack)-1] + } + if s.kind < 0 { + s.kinderr = nil + // Don't read further if we're at the end of the + // innermost list. + if tos != nil && tos.pos == tos.size { + return 0, 0, EOL + } + s.kind, s.size, s.kinderr = s.readKind() + if s.kinderr == nil { + if tos == nil { + // At toplevel, check that the value is smaller + // than the remaining input length. + if s.limited && s.size > s.remaining { + s.kinderr = ErrValueTooLarge + } + } else { + // Inside a list, check that the value doesn't overflow the list. + if s.size > tos.size-tos.pos { + s.kinderr = ErrElemTooLarge + } + } + } + } + // Note: this might return a sticky error generated + // by an earlier call to readKind. + return s.kind, s.size, s.kinderr +} + +func (s *Stream) readKind() (kind Kind, size uint64, err error) { + b, err := s.readByte() + if err != nil { + if len(s.stack) == 0 { + // At toplevel, Adjust the error to actual EOF. io.EOF is + // used by callers to determine when to stop decoding. + switch err { + case io.ErrUnexpectedEOF: + err = io.EOF + case ErrValueTooLarge: + err = io.EOF + } + } + return 0, 0, err + } + s.byteval = 0 + switch { + case b < 0x80: + // For a single byte whose value is in the [0x00, 0x7F] range, that byte + // is its own RLP encoding. + s.byteval = b + return Byte, 0, nil + case b < 0xB8: + // Otherwise, if a string is 0-55 bytes long, + // the RLP encoding consists of a single byte with value 0x80 plus the + // length of the string followed by the string. The range of the first + // byte is thus [0x80, 0xB7]. + return String, uint64(b - 0x80), nil + case b < 0xC0: + // If a string is more than 55 bytes long, the + // RLP encoding consists of a single byte with value 0xB7 plus the length + // of the length of the string in binary form, followed by the length of + // the string, followed by the string. For example, a length-1024 string + // would be encoded as 0xB90400 followed by the string. The range of + // the first byte is thus [0xB8, 0xBF]. + size, err = s.readUint(b - 0xB7) + if err == nil && size < 56 { + err = ErrCanonSize + } + return String, size, err + case b < 0xF8: + // If the total payload of a list + // (i.e. the combined length of all its items) is 0-55 bytes long, the + // RLP encoding consists of a single byte with value 0xC0 plus the length + // of the list followed by the concatenation of the RLP encodings of the + // items. The range of the first byte is thus [0xC0, 0xF7]. + return List, uint64(b - 0xC0), nil + default: + // If the total payload of a list is more than 55 bytes long, + // the RLP encoding consists of a single byte with value 0xF7 + // plus the length of the length of the payload in binary + // form, followed by the length of the payload, followed by + // the concatenation of the RLP encodings of the items. The + // range of the first byte is thus [0xF8, 0xFF]. + size, err = s.readUint(b - 0xF7) + if err == nil && size < 56 { + err = ErrCanonSize + } + return List, size, err + } +} + +func (s *Stream) readUint(size byte) (uint64, error) { + switch size { + case 0: + s.kind = -1 // rearm Kind + return 0, nil + case 1: + b, err := s.readByte() + return uint64(b), err + default: + start := int(8 - size) + for i := 0; i < start; i++ { + s.uintbuf[i] = 0 + } + if err := s.readFull(s.uintbuf[start:]); err != nil { + return 0, err + } + if s.uintbuf[start] == 0 { + // Note: readUint is also used to decode integer + // values. The error needs to be adjusted to become + // ErrCanonInt in this case. + return 0, ErrCanonSize + } + return binary.BigEndian.Uint64(s.uintbuf), nil + } +} + +func (s *Stream) readFull(buf []byte) (err error) { + if err := s.willRead(uint64(len(buf))); err != nil { + return err + } + var nn, n int + for n < len(buf) && err == nil { + nn, err = s.r.Read(buf[n:]) + n += nn + } + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return err +} + +func (s *Stream) readByte() (byte, error) { + if err := s.willRead(1); err != nil { + return 0, err + } + b, err := s.r.ReadByte() + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return b, err +} + +func (s *Stream) willRead(n uint64) error { + s.kind = -1 // rearm Kind + + if len(s.stack) > 0 { + // check list overflow + tos := s.stack[len(s.stack)-1] + if n > tos.size-tos.pos { + return ErrElemTooLarge + } + s.stack[len(s.stack)-1].pos += n + } + if s.limited { + if n > s.remaining { + return ErrValueTooLarge + } + s.remaining -= n + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/doc.go b/vendor/github.com/ethereum/go-ethereum/rlp/doc.go new file mode 100644 index 00000000..b3a81fe2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rlp/doc.go @@ -0,0 +1,33 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +/* +Package rlp implements the RLP serialization format. + +The purpose of RLP (Recursive Linear Prefix) is to encode arbitrarily +nested arrays of binary data, and RLP is the main encoding method used +to serialize objects in Ethereum. The only purpose of RLP is to encode +structure; encoding specific atomic data types (eg. strings, ints, +floats) is left up to higher-order protocols; in Ethereum integers +must be represented in big endian binary form with no leading zeroes +(thus making the integer value zero equivalent to the empty byte +array). + +RLP values are distinguished by a type tag. The type tag precedes the +value in the input stream and defines the size and kind of the bytes +that follow. +*/ +package rlp diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/encode.go b/vendor/github.com/ethereum/go-ethereum/rlp/encode.go new file mode 100644 index 00000000..44592c2f --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rlp/encode.go @@ -0,0 +1,652 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rlp + +import ( + "fmt" + "io" + "math/big" + "reflect" + "sync" +) + +var ( + // Common encoded values. + // These are useful when implementing EncodeRLP. + EmptyString = []byte{0x80} + EmptyList = []byte{0xC0} +) + +// Encoder is implemented by types that require custom +// encoding rules or want to encode private fields. +type Encoder interface { + // EncodeRLP should write the RLP encoding of its receiver to w. + // If the implementation is a pointer method, it may also be + // called for nil pointers. + // + // Implementations should generate valid RLP. The data written is + // not verified at the moment, but a future version might. It is + // recommended to write only a single value but writing multiple + // values or no value at all is also permitted. + EncodeRLP(io.Writer) error +} + +// Encode writes the RLP encoding of val to w. Note that Encode may +// perform many small writes in some cases. Consider making w +// buffered. +// +// Encode uses the following type-dependent encoding rules: +// +// If the type implements the Encoder interface, Encode calls +// EncodeRLP. This is true even for nil pointers, please see the +// documentation for Encoder. +// +// To encode a pointer, the value being pointed to is encoded. For nil +// pointers, Encode will encode the zero value of the type. A nil +// pointer to a struct type always encodes as an empty RLP list. +// A nil pointer to an array encodes as an empty list (or empty string +// if the array has element type byte). +// +// Struct values are encoded as an RLP list of all their encoded +// public fields. Recursive struct types are supported. +// +// To encode slices and arrays, the elements are encoded as an RLP +// list of the value's elements. Note that arrays and slices with +// element type uint8 or byte are always encoded as an RLP string. +// +// A Go string is encoded as an RLP string. +// +// An unsigned integer value is encoded as an RLP string. Zero always +// encodes as an empty RLP string. Encode also supports *big.Int. +// +// An interface value encodes as the value contained in the interface. +// +// Boolean values are not supported, nor are signed integers, floating +// point numbers, maps, channels and functions. +func Encode(w io.Writer, val interface{}) error { + if outer, ok := w.(*encbuf); ok { + // Encode was called by some type's EncodeRLP. + // Avoid copying by writing to the outer encbuf directly. + return outer.encode(val) + } + eb := encbufPool.Get().(*encbuf) + defer encbufPool.Put(eb) + eb.reset() + if err := eb.encode(val); err != nil { + return err + } + return eb.toWriter(w) +} + +// EncodeBytes returns the RLP encoding of val. +// Please see the documentation of Encode for the encoding rules. +func EncodeToBytes(val interface{}) ([]byte, error) { + eb := encbufPool.Get().(*encbuf) + defer encbufPool.Put(eb) + eb.reset() + if err := eb.encode(val); err != nil { + return nil, err + } + return eb.toBytes(), nil +} + +// EncodeReader returns a reader from which the RLP encoding of val +// can be read. The returned size is the total size of the encoded +// data. +// +// Please see the documentation of Encode for the encoding rules. +func EncodeToReader(val interface{}) (size int, r io.Reader, err error) { + eb := encbufPool.Get().(*encbuf) + eb.reset() + if err := eb.encode(val); err != nil { + return 0, nil, err + } + return eb.size(), &encReader{buf: eb}, nil +} + +type encbuf struct { + str []byte // string data, contains everything except list headers + lheads []*listhead // all list headers + lhsize int // sum of sizes of all encoded list headers + sizebuf []byte // 9-byte auxiliary buffer for uint encoding +} + +type listhead struct { + offset int // index of this header in string data + size int // total size of encoded data (including list headers) +} + +// encode writes head to the given buffer, which must be at least +// 9 bytes long. It returns the encoded bytes. +func (head *listhead) encode(buf []byte) []byte { + return buf[:puthead(buf, 0xC0, 0xF7, uint64(head.size))] +} + +// headsize returns the size of a list or string header +// for a value of the given size. +func headsize(size uint64) int { + if size < 56 { + return 1 + } + return 1 + intsize(size) +} + +// puthead writes a list or string header to buf. +// buf must be at least 9 bytes long. +func puthead(buf []byte, smalltag, largetag byte, size uint64) int { + if size < 56 { + buf[0] = smalltag + byte(size) + return 1 + } else { + sizesize := putint(buf[1:], size) + buf[0] = largetag + byte(sizesize) + return sizesize + 1 + } +} + +// encbufs are pooled. +var encbufPool = sync.Pool{ + New: func() interface{} { return &encbuf{sizebuf: make([]byte, 9)} }, +} + +func (w *encbuf) reset() { + w.lhsize = 0 + if w.str != nil { + w.str = w.str[:0] + } + if w.lheads != nil { + w.lheads = w.lheads[:0] + } +} + +// encbuf implements io.Writer so it can be passed it into EncodeRLP. +func (w *encbuf) Write(b []byte) (int, error) { + w.str = append(w.str, b...) + return len(b), nil +} + +func (w *encbuf) encode(val interface{}) error { + rval := reflect.ValueOf(val) + ti, err := cachedTypeInfo(rval.Type(), tags{}) + if err != nil { + return err + } + return ti.writer(rval, w) +} + +func (w *encbuf) encodeStringHeader(size int) { + if size < 56 { + w.str = append(w.str, 0x80+byte(size)) + } else { + // TODO: encode to w.str directly + sizesize := putint(w.sizebuf[1:], uint64(size)) + w.sizebuf[0] = 0xB7 + byte(sizesize) + w.str = append(w.str, w.sizebuf[:sizesize+1]...) + } +} + +func (w *encbuf) encodeString(b []byte) { + if len(b) == 1 && b[0] <= 0x7F { + // fits single byte, no string header + w.str = append(w.str, b[0]) + } else { + w.encodeStringHeader(len(b)) + w.str = append(w.str, b...) + } +} + +func (w *encbuf) list() *listhead { + lh := &listhead{offset: len(w.str), size: w.lhsize} + w.lheads = append(w.lheads, lh) + return lh +} + +func (w *encbuf) listEnd(lh *listhead) { + lh.size = w.size() - lh.offset - lh.size + if lh.size < 56 { + w.lhsize += 1 // length encoded into kind tag + } else { + w.lhsize += 1 + intsize(uint64(lh.size)) + } +} + +func (w *encbuf) size() int { + return len(w.str) + w.lhsize +} + +func (w *encbuf) toBytes() []byte { + out := make([]byte, w.size()) + strpos := 0 + pos := 0 + for _, head := range w.lheads { + // write string data before header + n := copy(out[pos:], w.str[strpos:head.offset]) + pos += n + strpos += n + // write the header + enc := head.encode(out[pos:]) + pos += len(enc) + } + // copy string data after the last list header + copy(out[pos:], w.str[strpos:]) + return out +} + +func (w *encbuf) toWriter(out io.Writer) (err error) { + strpos := 0 + for _, head := range w.lheads { + // write string data before header + if head.offset-strpos > 0 { + n, err := out.Write(w.str[strpos:head.offset]) + strpos += n + if err != nil { + return err + } + } + // write the header + enc := head.encode(w.sizebuf) + if _, err = out.Write(enc); err != nil { + return err + } + } + if strpos < len(w.str) { + // write string data after the last list header + _, err = out.Write(w.str[strpos:]) + } + return err +} + +// encReader is the io.Reader returned by EncodeToReader. +// It releases its encbuf at EOF. +type encReader struct { + buf *encbuf // the buffer we're reading from. this is nil when we're at EOF. + lhpos int // index of list header that we're reading + strpos int // current position in string buffer + piece []byte // next piece to be read +} + +func (r *encReader) Read(b []byte) (n int, err error) { + for { + if r.piece = r.next(); r.piece == nil { + // Put the encode buffer back into the pool at EOF when it + // is first encountered. Subsequent calls still return EOF + // as the error but the buffer is no longer valid. + if r.buf != nil { + encbufPool.Put(r.buf) + r.buf = nil + } + return n, io.EOF + } + nn := copy(b[n:], r.piece) + n += nn + if nn < len(r.piece) { + // piece didn't fit, see you next time. + r.piece = r.piece[nn:] + return n, nil + } + r.piece = nil + } +} + +// next returns the next piece of data to be read. +// it returns nil at EOF. +func (r *encReader) next() []byte { + switch { + case r.buf == nil: + return nil + + case r.piece != nil: + // There is still data available for reading. + return r.piece + + case r.lhpos < len(r.buf.lheads): + // We're before the last list header. + head := r.buf.lheads[r.lhpos] + sizebefore := head.offset - r.strpos + if sizebefore > 0 { + // String data before header. + p := r.buf.str[r.strpos:head.offset] + r.strpos += sizebefore + return p + } else { + r.lhpos++ + return head.encode(r.buf.sizebuf) + } + + case r.strpos < len(r.buf.str): + // String data at the end, after all list headers. + p := r.buf.str[r.strpos:] + r.strpos = len(r.buf.str) + return p + + default: + return nil + } +} + +var ( + encoderInterface = reflect.TypeOf(new(Encoder)).Elem() + big0 = big.NewInt(0) +) + +// makeWriter creates a writer function for the given type. +func makeWriter(typ reflect.Type, ts tags) (writer, error) { + kind := typ.Kind() + switch { + case typ == rawValueType: + return writeRawValue, nil + case typ.Implements(encoderInterface): + return writeEncoder, nil + case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface): + return writeEncoderNoPtr, nil + case kind == reflect.Interface: + return writeInterface, nil + case typ.AssignableTo(reflect.PtrTo(bigInt)): + return writeBigIntPtr, nil + case typ.AssignableTo(bigInt): + return writeBigIntNoPtr, nil + case isUint(kind): + return writeUint, nil + case kind == reflect.Bool: + return writeBool, nil + case kind == reflect.String: + return writeString, nil + case kind == reflect.Slice && isByte(typ.Elem()): + return writeBytes, nil + case kind == reflect.Array && isByte(typ.Elem()): + return writeByteArray, nil + case kind == reflect.Slice || kind == reflect.Array: + return makeSliceWriter(typ, ts) + case kind == reflect.Struct: + return makeStructWriter(typ) + case kind == reflect.Ptr: + return makePtrWriter(typ) + default: + return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ) + } +} + +func isByte(typ reflect.Type) bool { + return typ.Kind() == reflect.Uint8 && !typ.Implements(encoderInterface) +} + +func writeRawValue(val reflect.Value, w *encbuf) error { + w.str = append(w.str, val.Bytes()...) + return nil +} + +func writeUint(val reflect.Value, w *encbuf) error { + i := val.Uint() + if i == 0 { + w.str = append(w.str, 0x80) + } else if i < 128 { + // fits single byte + w.str = append(w.str, byte(i)) + } else { + // TODO: encode int to w.str directly + s := putint(w.sizebuf[1:], i) + w.sizebuf[0] = 0x80 + byte(s) + w.str = append(w.str, w.sizebuf[:s+1]...) + } + return nil +} + +func writeBool(val reflect.Value, w *encbuf) error { + if val.Bool() { + w.str = append(w.str, 0x01) + } else { + w.str = append(w.str, 0x80) + } + return nil +} + +func writeBigIntPtr(val reflect.Value, w *encbuf) error { + ptr := val.Interface().(*big.Int) + if ptr == nil { + w.str = append(w.str, 0x80) + return nil + } + return writeBigInt(ptr, w) +} + +func writeBigIntNoPtr(val reflect.Value, w *encbuf) error { + i := val.Interface().(big.Int) + return writeBigInt(&i, w) +} + +func writeBigInt(i *big.Int, w *encbuf) error { + if cmp := i.Cmp(big0); cmp == -1 { + return fmt.Errorf("rlp: cannot encode negative *big.Int") + } else if cmp == 0 { + w.str = append(w.str, 0x80) + } else { + w.encodeString(i.Bytes()) + } + return nil +} + +func writeBytes(val reflect.Value, w *encbuf) error { + w.encodeString(val.Bytes()) + return nil +} + +func writeByteArray(val reflect.Value, w *encbuf) error { + if !val.CanAddr() { + // Slice requires the value to be addressable. + // Make it addressable by copying. + copy := reflect.New(val.Type()).Elem() + copy.Set(val) + val = copy + } + size := val.Len() + slice := val.Slice(0, size).Bytes() + w.encodeString(slice) + return nil +} + +func writeString(val reflect.Value, w *encbuf) error { + s := val.String() + if len(s) == 1 && s[0] <= 0x7f { + // fits single byte, no string header + w.str = append(w.str, s[0]) + } else { + w.encodeStringHeader(len(s)) + w.str = append(w.str, s...) + } + return nil +} + +func writeEncoder(val reflect.Value, w *encbuf) error { + return val.Interface().(Encoder).EncodeRLP(w) +} + +// writeEncoderNoPtr handles non-pointer values that implement Encoder +// with a pointer receiver. +func writeEncoderNoPtr(val reflect.Value, w *encbuf) error { + if !val.CanAddr() { + // We can't get the address. It would be possible to make the + // value addressable by creating a shallow copy, but this + // creates other problems so we're not doing it (yet). + // + // package json simply doesn't call MarshalJSON for cases like + // this, but encodes the value as if it didn't implement the + // interface. We don't want to handle it that way. + return fmt.Errorf("rlp: game over: unadressable value of type %v, EncodeRLP is pointer method", val.Type()) + } + return val.Addr().Interface().(Encoder).EncodeRLP(w) +} + +func writeInterface(val reflect.Value, w *encbuf) error { + if val.IsNil() { + // Write empty list. This is consistent with the previous RLP + // encoder that we had and should therefore avoid any + // problems. + w.str = append(w.str, 0xC0) + return nil + } + eval := val.Elem() + ti, err := cachedTypeInfo(eval.Type(), tags{}) + if err != nil { + return err + } + return ti.writer(eval, w) +} + +func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) { + etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{}) + if err != nil { + return nil, err + } + writer := func(val reflect.Value, w *encbuf) error { + if !ts.tail { + defer w.listEnd(w.list()) + } + vlen := val.Len() + for i := 0; i < vlen; i++ { + if err := etypeinfo.writer(val.Index(i), w); err != nil { + return err + } + } + return nil + } + return writer, nil +} + +func makeStructWriter(typ reflect.Type) (writer, error) { + fields, err := structFields(typ) + if err != nil { + return nil, err + } + writer := func(val reflect.Value, w *encbuf) error { + lh := w.list() + for _, f := range fields { + if err := f.info.writer(val.Field(f.index), w); err != nil { + return err + } + } + w.listEnd(lh) + return nil + } + return writer, nil +} + +func makePtrWriter(typ reflect.Type) (writer, error) { + etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{}) + if err != nil { + return nil, err + } + + // determine nil pointer handler + var nilfunc func(*encbuf) error + kind := typ.Elem().Kind() + switch { + case kind == reflect.Array && isByte(typ.Elem().Elem()): + nilfunc = func(w *encbuf) error { + w.str = append(w.str, 0x80) + return nil + } + case kind == reflect.Struct || kind == reflect.Array: + nilfunc = func(w *encbuf) error { + // encoding the zero value of a struct/array could trigger + // infinite recursion, avoid that. + w.listEnd(w.list()) + return nil + } + default: + zero := reflect.Zero(typ.Elem()) + nilfunc = func(w *encbuf) error { + return etypeinfo.writer(zero, w) + } + } + + writer := func(val reflect.Value, w *encbuf) error { + if val.IsNil() { + return nilfunc(w) + } else { + return etypeinfo.writer(val.Elem(), w) + } + } + return writer, err +} + +// putint writes i to the beginning of b in big endian byte +// order, using the least number of bytes needed to represent i. +func putint(b []byte, i uint64) (size int) { + switch { + case i < (1 << 8): + b[0] = byte(i) + return 1 + case i < (1 << 16): + b[0] = byte(i >> 8) + b[1] = byte(i) + return 2 + case i < (1 << 24): + b[0] = byte(i >> 16) + b[1] = byte(i >> 8) + b[2] = byte(i) + return 3 + case i < (1 << 32): + b[0] = byte(i >> 24) + b[1] = byte(i >> 16) + b[2] = byte(i >> 8) + b[3] = byte(i) + return 4 + case i < (1 << 40): + b[0] = byte(i >> 32) + b[1] = byte(i >> 24) + b[2] = byte(i >> 16) + b[3] = byte(i >> 8) + b[4] = byte(i) + return 5 + case i < (1 << 48): + b[0] = byte(i >> 40) + b[1] = byte(i >> 32) + b[2] = byte(i >> 24) + b[3] = byte(i >> 16) + b[4] = byte(i >> 8) + b[5] = byte(i) + return 6 + case i < (1 << 56): + b[0] = byte(i >> 48) + b[1] = byte(i >> 40) + b[2] = byte(i >> 32) + b[3] = byte(i >> 24) + b[4] = byte(i >> 16) + b[5] = byte(i >> 8) + b[6] = byte(i) + return 7 + default: + b[0] = byte(i >> 56) + b[1] = byte(i >> 48) + b[2] = byte(i >> 40) + b[3] = byte(i >> 32) + b[4] = byte(i >> 24) + b[5] = byte(i >> 16) + b[6] = byte(i >> 8) + b[7] = byte(i) + return 8 + } +} + +// intsize computes the minimum number of bytes required to store i. +func intsize(i uint64) (size int) { + for size = 1; ; size++ { + if i >>= 8; i == 0 { + return size + } + } +} diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/raw.go b/vendor/github.com/ethereum/go-ethereum/rlp/raw.go new file mode 100644 index 00000000..6bf1c1df --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rlp/raw.go @@ -0,0 +1,156 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rlp + +import ( + "io" + "reflect" +) + +// RawValue represents an encoded RLP value and can be used to delay +// RLP decoding or to precompute an encoding. Note that the decoder does +// not verify whether the content of RawValues is valid RLP. +type RawValue []byte + +var rawValueType = reflect.TypeOf(RawValue{}) + +// ListSize returns the encoded size of an RLP list with the given +// content size. +func ListSize(contentSize uint64) uint64 { + return uint64(headsize(contentSize)) + contentSize +} + +// Split returns the content of first RLP value and any +// bytes after the value as subslices of b. +func Split(b []byte) (k Kind, content, rest []byte, err error) { + k, ts, cs, err := readKind(b) + if err != nil { + return 0, nil, b, err + } + return k, b[ts : ts+cs], b[ts+cs:], nil +} + +// SplitString splits b into the content of an RLP string +// and any remaining bytes after the string. +func SplitString(b []byte) (content, rest []byte, err error) { + k, content, rest, err := Split(b) + if err != nil { + return nil, b, err + } + if k == List { + return nil, b, ErrExpectedString + } + return content, rest, nil +} + +// SplitList splits b into the content of a list and any remaining +// bytes after the list. +func SplitList(b []byte) (content, rest []byte, err error) { + k, content, rest, err := Split(b) + if err != nil { + return nil, b, err + } + if k != List { + return nil, b, ErrExpectedList + } + return content, rest, nil +} + +// CountValues counts the number of encoded values in b. +func CountValues(b []byte) (int, error) { + i := 0 + for ; len(b) > 0; i++ { + _, tagsize, size, err := readKind(b) + if err != nil { + return 0, err + } + b = b[tagsize+size:] + } + return i, nil +} + +func readKind(buf []byte) (k Kind, tagsize, contentsize uint64, err error) { + if len(buf) == 0 { + return 0, 0, 0, io.ErrUnexpectedEOF + } + b := buf[0] + switch { + case b < 0x80: + k = Byte + tagsize = 0 + contentsize = 1 + case b < 0xB8: + k = String + tagsize = 1 + contentsize = uint64(b - 0x80) + // Reject strings that should've been single bytes. + if contentsize == 1 && buf[1] < 128 { + return 0, 0, 0, ErrCanonSize + } + case b < 0xC0: + k = String + tagsize = uint64(b-0xB7) + 1 + contentsize, err = readSize(buf[1:], b-0xB7) + case b < 0xF8: + k = List + tagsize = 1 + contentsize = uint64(b - 0xC0) + default: + k = List + tagsize = uint64(b-0xF7) + 1 + contentsize, err = readSize(buf[1:], b-0xF7) + } + if err != nil { + return 0, 0, 0, err + } + // Reject values larger than the input slice. + if contentsize > uint64(len(buf))-tagsize { + return 0, 0, 0, ErrValueTooLarge + } + return k, tagsize, contentsize, err +} + +func readSize(b []byte, slen byte) (uint64, error) { + if int(slen) > len(b) { + return 0, io.ErrUnexpectedEOF + } + var s uint64 + switch slen { + case 1: + s = uint64(b[0]) + case 2: + s = uint64(b[0])<<8 | uint64(b[1]) + case 3: + s = uint64(b[0])<<16 | uint64(b[1])<<8 | uint64(b[2]) + case 4: + s = uint64(b[0])<<24 | uint64(b[1])<<16 | uint64(b[2])<<8 | uint64(b[3]) + case 5: + s = uint64(b[0])<<32 | uint64(b[1])<<24 | uint64(b[2])<<16 | uint64(b[3])<<8 | uint64(b[4]) + case 6: + s = uint64(b[0])<<40 | uint64(b[1])<<32 | uint64(b[2])<<24 | uint64(b[3])<<16 | uint64(b[4])<<8 | uint64(b[5]) + case 7: + s = uint64(b[0])<<48 | uint64(b[1])<<40 | uint64(b[2])<<32 | uint64(b[3])<<24 | uint64(b[4])<<16 | uint64(b[5])<<8 | uint64(b[6]) + case 8: + s = uint64(b[0])<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 | uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7]) + } + // Reject sizes < 56 (shouldn't have separate size) and sizes with + // leading zero bytes. + if s < 56 || b[0] == 0 { + return 0, ErrCanonSize + } + return s, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go b/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go new file mode 100644 index 00000000..3df799e1 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/rlp/typecache.go @@ -0,0 +1,156 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rlp + +import ( + "fmt" + "reflect" + "strings" + "sync" +) + +var ( + typeCacheMutex sync.RWMutex + typeCache = make(map[typekey]*typeinfo) +) + +type typeinfo struct { + decoder + writer +} + +// represents struct tags +type tags struct { + // rlp:"nil" controls whether empty input results in a nil pointer. + nilOK bool + // rlp:"tail" controls whether this field swallows additional list + // elements. It can only be set for the last field, which must be + // of slice type. + tail bool + // rlp:"-" ignores fields. + ignored bool +} + +type typekey struct { + reflect.Type + // the key must include the struct tags because they + // might generate a different decoder. + tags +} + +type decoder func(*Stream, reflect.Value) error + +type writer func(reflect.Value, *encbuf) error + +func cachedTypeInfo(typ reflect.Type, tags tags) (*typeinfo, error) { + typeCacheMutex.RLock() + info := typeCache[typekey{typ, tags}] + typeCacheMutex.RUnlock() + if info != nil { + return info, nil + } + // not in the cache, need to generate info for this type. + typeCacheMutex.Lock() + defer typeCacheMutex.Unlock() + return cachedTypeInfo1(typ, tags) +} + +func cachedTypeInfo1(typ reflect.Type, tags tags) (*typeinfo, error) { + key := typekey{typ, tags} + info := typeCache[key] + if info != nil { + // another goroutine got the write lock first + return info, nil + } + // put a dummmy value into the cache before generating. + // if the generator tries to lookup itself, it will get + // the dummy value and won't call itself recursively. + typeCache[key] = new(typeinfo) + info, err := genTypeInfo(typ, tags) + if err != nil { + // remove the dummy value if the generator fails + delete(typeCache, key) + return nil, err + } + *typeCache[key] = *info + return typeCache[key], err +} + +type field struct { + index int + info *typeinfo +} + +func structFields(typ reflect.Type) (fields []field, err error) { + for i := 0; i < typ.NumField(); i++ { + if f := typ.Field(i); f.PkgPath == "" { // exported + tags, err := parseStructTag(typ, i) + if err != nil { + return nil, err + } + if tags.ignored { + continue + } + info, err := cachedTypeInfo1(f.Type, tags) + if err != nil { + return nil, err + } + fields = append(fields, field{i, info}) + } + } + return fields, nil +} + +func parseStructTag(typ reflect.Type, fi int) (tags, error) { + f := typ.Field(fi) + var ts tags + for _, t := range strings.Split(f.Tag.Get("rlp"), ",") { + switch t = strings.TrimSpace(t); t { + case "": + case "-": + ts.ignored = true + case "nil": + ts.nilOK = true + case "tail": + ts.tail = true + if fi != typ.NumField()-1 { + return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (must be on last field)`, typ, f.Name) + } + if f.Type.Kind() != reflect.Slice { + return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (field type is not slice)`, typ, f.Name) + } + default: + return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name) + } + } + return ts, nil +} + +func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) { + info = new(typeinfo) + if info.decoder, err = makeDecoder(typ, tags); err != nil { + return nil, err + } + if info.writer, err = makeWriter(typ, tags); err != nil { + return nil, err + } + return info, nil +} + +func isUint(k reflect.Kind) bool { + return k >= reflect.Uint && k <= reflect.Uintptr +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/encoding.go b/vendor/github.com/ethereum/go-ethereum/trie/encoding.go new file mode 100644 index 00000000..e96a786e --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/encoding.go @@ -0,0 +1,114 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +// Trie keys are dealt with in three distinct encodings: +// +// KEYBYTES encoding contains the actual key and nothing else. This encoding is the +// input to most API functions. +// +// HEX encoding contains one byte for each nibble of the key and an optional trailing +// 'terminator' byte of value 0x10 which indicates whether or not the node at the key +// contains a value. Hex key encoding is used for nodes loaded in memory because it's +// convenient to access. +// +// COMPACT encoding is defined by the Ethereum Yellow Paper (it's called "hex prefix +// encoding" there) and contains the bytes of the key and a flag. The high nibble of the +// first byte contains the flag; the lowest bit encoding the oddness of the length and +// the second-lowest encoding whether the node at the key is a value node. The low nibble +// of the first byte is zero in the case of an even number of nibbles and the first nibble +// in the case of an odd number. All remaining nibbles (now an even number) fit properly +// into the remaining bytes. Compact encoding is used for nodes stored on disk. + +func hexToCompact(hex []byte) []byte { + terminator := byte(0) + if hasTerm(hex) { + terminator = 1 + hex = hex[:len(hex)-1] + } + buf := make([]byte, len(hex)/2+1) + buf[0] = terminator << 5 // the flag byte + if len(hex)&1 == 1 { + buf[0] |= 1 << 4 // odd flag + buf[0] |= hex[0] // first nibble is contained in the first byte + hex = hex[1:] + } + decodeNibbles(hex, buf[1:]) + return buf +} + +func compactToHex(compact []byte) []byte { + base := keybytesToHex(compact) + base = base[:len(base)-1] + // apply terminator flag + if base[0] >= 2 { + base = append(base, 16) + } + // apply odd flag + chop := 2 - base[0]&1 + return base[chop:] +} + +func keybytesToHex(str []byte) []byte { + l := len(str)*2 + 1 + var nibbles = make([]byte, l) + for i, b := range str { + nibbles[i*2] = b / 16 + nibbles[i*2+1] = b % 16 + } + nibbles[l-1] = 16 + return nibbles +} + +// hexToKeybytes turns hex nibbles into key bytes. +// This can only be used for keys of even length. +func hexToKeybytes(hex []byte) []byte { + if hasTerm(hex) { + hex = hex[:len(hex)-1] + } + if len(hex)&1 != 0 { + panic("can't convert hex key of odd length") + } + key := make([]byte, (len(hex)+1)/2) + decodeNibbles(hex, key) + return key +} + +func decodeNibbles(nibbles []byte, bytes []byte) { + for bi, ni := 0, 0; ni < len(nibbles); bi, ni = bi+1, ni+2 { + bytes[bi] = nibbles[ni]<<4 | nibbles[ni+1] + } +} + +// prefixLen returns the length of the common prefix of a and b. +func prefixLen(a, b []byte) int { + var i, length = 0, len(a) + if len(b) < length { + length = len(b) + } + for ; i < length; i++ { + if a[i] != b[i] { + break + } + } + return i +} + +// hasTerm returns whether a hex key has the terminator flag. +func hasTerm(s []byte) bool { + return len(s) > 0 && s[len(s)-1] == 16 +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/errors.go b/vendor/github.com/ethereum/go-ethereum/trie/errors.go new file mode 100644 index 00000000..e23f9d56 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/errors.go @@ -0,0 +1,46 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" +) + +// MissingNodeError is returned by the trie functions (TryGet, TryUpdate, TryDelete) +// in the case where a trie node is not present in the local database. Contains +// information necessary for retrieving the missing node through an ODR service. +// +// NodeHash is the hash of the missing node +// +// RootHash is the original root of the trie that contains the node +// +// PrefixLen is the nibble length of the key prefix that leads from the root to +// the missing node +// +// SuffixLen is the nibble length of the remaining part of the key that hints on +// which further nodes should also be retrieved (can be zero when there are no +// such hints in the error message) +type MissingNodeError struct { + RootHash, NodeHash common.Hash + PrefixLen, SuffixLen int +} + +func (err *MissingNodeError) Error() string { + return fmt.Sprintf("Missing trie node %064x", err.NodeHash) +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/hasher.go b/vendor/github.com/ethereum/go-ethereum/trie/hasher.go new file mode 100644 index 00000000..672456e2 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/hasher.go @@ -0,0 +1,173 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +import ( + "bytes" + "hash" + "sync" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto/sha3" + "github.com/ethereum/go-ethereum/rlp" +) + +type hasher struct { + tmp *bytes.Buffer + sha hash.Hash + cachegen, cachelimit uint16 +} + +// hashers live in a global pool. +var hasherPool = sync.Pool{ + New: func() interface{} { + return &hasher{tmp: new(bytes.Buffer), sha: sha3.NewKeccak256()} + }, +} + +func newHasher(cachegen, cachelimit uint16) *hasher { + h := hasherPool.Get().(*hasher) + h.cachegen, h.cachelimit = cachegen, cachelimit + return h +} + +func returnHasherToPool(h *hasher) { + hasherPool.Put(h) +} + +// hash collapses a node down into a hash node, also returning a copy of the +// original node initialized with the computed hash to replace the original one. +func (h *hasher) hash(n node, db DatabaseWriter, force bool) (node, node, error) { + // If we're not storing the node, just hashing, use available cached data + if hash, dirty := n.cache(); hash != nil { + if db == nil { + return hash, n, nil + } + if n.canUnload(h.cachegen, h.cachelimit) { + // Unload the node from cache. All of its subnodes will have a lower or equal + // cache generation number. + cacheUnloadCounter.Inc(1) + return hash, hash, nil + } + if !dirty { + return hash, n, nil + } + } + // Trie not processed yet or needs storage, walk the children + collapsed, cached, err := h.hashChildren(n, db) + if err != nil { + return hashNode{}, n, err + } + hashed, err := h.store(collapsed, db, force) + if err != nil { + return hashNode{}, n, err + } + // Cache the hash of the ndoe for later reuse and remove + // the dirty flag in commit mode. It's fine to assign these values directly + // without copying the node first because hashChildren copies it. + cachedHash, _ := hashed.(hashNode) + switch cn := cached.(type) { + case *shortNode: + cn.flags.hash = cachedHash + if db != nil { + cn.flags.dirty = false + } + case *fullNode: + cn.flags.hash = cachedHash + if db != nil { + cn.flags.dirty = false + } + } + return hashed, cached, nil +} + +// hashChildren replaces the children of a node with their hashes if the encoded +// size of the child is larger than a hash, returning the collapsed node as well +// as a replacement for the original node with the child hashes cached in. +func (h *hasher) hashChildren(original node, db DatabaseWriter) (node, node, error) { + var err error + + switch n := original.(type) { + case *shortNode: + // Hash the short node's child, caching the newly hashed subtree + collapsed, cached := n.copy(), n.copy() + collapsed.Key = hexToCompact(n.Key) + cached.Key = common.CopyBytes(n.Key) + + if _, ok := n.Val.(valueNode); !ok { + collapsed.Val, cached.Val, err = h.hash(n.Val, db, false) + if err != nil { + return original, original, err + } + } + if collapsed.Val == nil { + collapsed.Val = valueNode(nil) // Ensure that nil children are encoded as empty strings. + } + return collapsed, cached, nil + + case *fullNode: + // Hash the full node's children, caching the newly hashed subtrees + collapsed, cached := n.copy(), n.copy() + + for i := 0; i < 16; i++ { + if n.Children[i] != nil { + collapsed.Children[i], cached.Children[i], err = h.hash(n.Children[i], db, false) + if err != nil { + return original, original, err + } + } else { + collapsed.Children[i] = valueNode(nil) // Ensure that nil children are encoded as empty strings. + } + } + cached.Children[16] = n.Children[16] + if collapsed.Children[16] == nil { + collapsed.Children[16] = valueNode(nil) + } + return collapsed, cached, nil + + default: + // Value and hash nodes don't have children so they're left as were + return n, original, nil + } +} + +func (h *hasher) store(n node, db DatabaseWriter, force bool) (node, error) { + // Don't store hashes or empty nodes. + if _, isHash := n.(hashNode); n == nil || isHash { + return n, nil + } + // Generate the RLP encoding of the node + h.tmp.Reset() + if err := rlp.Encode(h.tmp, n); err != nil { + panic("encode error: " + err.Error()) + } + + if h.tmp.Len() < 32 && !force { + return n, nil // Nodes smaller than 32 bytes are stored inside their parent + } + // Larger nodes are replaced by their hash and stored in the database. + hash, _ := n.cache() + if hash == nil { + h.sha.Reset() + h.sha.Write(h.tmp.Bytes()) + hash = hashNode(h.sha.Sum(nil)) + } + if db != nil { + return hash, db.Put(hash, h.tmp.Bytes()) + } + return hash, nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/iterator.go b/vendor/github.com/ethereum/go-ethereum/trie/iterator.go new file mode 100644 index 00000000..26ae1d5a --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/iterator.go @@ -0,0 +1,499 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +import ( + "bytes" + "container/heap" + "errors" + + "github.com/ethereum/go-ethereum/common" +) + +var iteratorEnd = errors.New("end of iteration") + +// Iterator is a key-value trie iterator that traverses a Trie. +type Iterator struct { + nodeIt NodeIterator + + Key []byte // Current data key on which the iterator is positioned on + Value []byte // Current data value on which the iterator is positioned on +} + +// NewIterator creates a new key-value iterator from a node iterator +func NewIterator(it NodeIterator) *Iterator { + return &Iterator{ + nodeIt: it, + } +} + +// Next moves the iterator forward one key-value entry. +func (it *Iterator) Next() bool { + for it.nodeIt.Next(true) { + if it.nodeIt.Leaf() { + it.Key = hexToKeybytes(it.nodeIt.Path()) + it.Value = it.nodeIt.LeafBlob() + return true + } + } + it.Key = nil + it.Value = nil + return false +} + +// NodeIterator is an iterator to traverse the trie pre-order. +type NodeIterator interface { + // Hash returns the hash of the current node + Hash() common.Hash + // Parent returns the hash of the parent of the current node + Parent() common.Hash + // Leaf returns true iff the current node is a leaf node. + Leaf() bool + // LeafBlob returns the contents of the node, if it is a leaf. + // Callers must not retain references to the return value after calling Next() + LeafBlob() []byte + // Path returns the hex-encoded path to the current node. + // Callers must not retain references to the return value after calling Next() + Path() []byte + // Next moves the iterator to the next node. If the parameter is false, any child + // nodes will be skipped. + Next(bool) bool + // Error returns the error status of the iterator. + Error() error +} + +// nodeIteratorState represents the iteration state at one particular node of the +// trie, which can be resumed at a later invocation. +type nodeIteratorState struct { + hash common.Hash // Hash of the node being iterated (nil if not standalone) + node node // Trie node being iterated + parent common.Hash // Hash of the first full ancestor node (nil if current is the root) + index int // Child to be processed next + pathlen int // Length of the path to this node +} + +type nodeIterator struct { + trie *Trie // Trie being iterated + stack []*nodeIteratorState // Hierarchy of trie nodes persisting the iteration state + err error // Failure set in case of an internal error in the iterator + path []byte // Path to the current node +} + +func newNodeIterator(trie *Trie, start []byte) NodeIterator { + if trie.Hash() == emptyState { + return new(nodeIterator) + } + it := &nodeIterator{trie: trie} + it.seek(start) + return it +} + +// Hash returns the hash of the current node +func (it *nodeIterator) Hash() common.Hash { + if len(it.stack) == 0 { + return common.Hash{} + } + + return it.stack[len(it.stack)-1].hash +} + +// Parent returns the hash of the parent node +func (it *nodeIterator) Parent() common.Hash { + if len(it.stack) == 0 { + return common.Hash{} + } + + return it.stack[len(it.stack)-1].parent +} + +// Leaf returns true if the current node is a leaf +func (it *nodeIterator) Leaf() bool { + if len(it.stack) == 0 { + return false + } + + _, ok := it.stack[len(it.stack)-1].node.(valueNode) + return ok +} + +// LeafBlob returns the data for the current node, if it is a leaf +func (it *nodeIterator) LeafBlob() []byte { + if len(it.stack) == 0 { + return nil + } + + if node, ok := it.stack[len(it.stack)-1].node.(valueNode); ok { + return []byte(node) + } + return nil +} + +// Path returns the hex-encoded path to the current node +func (it *nodeIterator) Path() []byte { + return it.path +} + +// Error returns the error set in case of an internal error in the iterator +func (it *nodeIterator) Error() error { + if it.err == iteratorEnd { + return nil + } + return it.err +} + +// Next moves the iterator to the next node, returning whether there are any +// further nodes. In case of an internal error this method returns false and +// sets the Error field to the encountered failure. If `descend` is false, +// skips iterating over any subnodes of the current node. +func (it *nodeIterator) Next(descend bool) bool { + if it.err != nil { + return false + } + // Otherwise step forward with the iterator and report any errors + state, parentIndex, path, err := it.peek(descend) + if err != nil { + it.err = err + return false + } + it.push(state, parentIndex, path) + return true +} + +func (it *nodeIterator) seek(prefix []byte) { + // The path we're looking for is the hex encoded key without terminator. + key := keybytesToHex(prefix) + key = key[:len(key)-1] + // Move forward until we're just before the closest match to key. + for { + state, parentIndex, path, err := it.peek(bytes.HasPrefix(key, it.path)) + if err != nil || bytes.Compare(path, key) >= 0 { + it.err = err + return + } + it.push(state, parentIndex, path) + } +} + +// peek creates the next state of the iterator. +func (it *nodeIterator) peek(descend bool) (*nodeIteratorState, *int, []byte, error) { + if len(it.stack) == 0 { + // Initialize the iterator if we've just started. + root := it.trie.Hash() + state := &nodeIteratorState{node: it.trie.root, index: -1} + if root != emptyRoot { + state.hash = root + } + return state, nil, nil, nil + } + if !descend { + // If we're skipping children, pop the current node first + it.pop() + } + + // Continue iteration to the next child + for { + if len(it.stack) == 0 { + return nil, nil, nil, iteratorEnd + } + parent := it.stack[len(it.stack)-1] + ancestor := parent.hash + if (ancestor == common.Hash{}) { + ancestor = parent.parent + } + if node, ok := parent.node.(*fullNode); ok { + // Full node, move to the first non-nil child. + for i := parent.index + 1; i < len(node.Children); i++ { + child := node.Children[i] + if child != nil { + hash, _ := child.cache() + state := &nodeIteratorState{ + hash: common.BytesToHash(hash), + node: child, + parent: ancestor, + index: -1, + pathlen: len(it.path), + } + path := append(it.path, byte(i)) + parent.index = i - 1 + return state, &parent.index, path, nil + } + } + } else if node, ok := parent.node.(*shortNode); ok { + // Short node, return the pointer singleton child + if parent.index < 0 { + hash, _ := node.Val.cache() + state := &nodeIteratorState{ + hash: common.BytesToHash(hash), + node: node.Val, + parent: ancestor, + index: -1, + pathlen: len(it.path), + } + var path []byte + if hasTerm(node.Key) { + path = append(it.path, node.Key[:len(node.Key)-1]...) + } else { + path = append(it.path, node.Key...) + } + return state, &parent.index, path, nil + } + } else if hash, ok := parent.node.(hashNode); ok { + // Hash node, resolve the hash child from the database + if parent.index < 0 { + node, err := it.trie.resolveHash(hash, nil, nil) + if err != nil { + return it.stack[len(it.stack)-1], &parent.index, it.path, err + } + state := &nodeIteratorState{ + hash: common.BytesToHash(hash), + node: node, + parent: ancestor, + index: -1, + pathlen: len(it.path), + } + return state, &parent.index, it.path, nil + } + } + // No more child nodes, move back up. + it.pop() + } +} + +func (it *nodeIterator) push(state *nodeIteratorState, parentIndex *int, path []byte) { + it.path = path + it.stack = append(it.stack, state) + if parentIndex != nil { + *parentIndex += 1 + } +} + +func (it *nodeIterator) pop() { + parent := it.stack[len(it.stack)-1] + it.path = it.path[:parent.pathlen] + it.stack = it.stack[:len(it.stack)-1] +} + +func compareNodes(a, b NodeIterator) int { + cmp := bytes.Compare(a.Path(), b.Path()) + if cmp != 0 { + return cmp + } + + if a.Leaf() && !b.Leaf() { + return -1 + } else if b.Leaf() && !a.Leaf() { + return 1 + } + + cmp = bytes.Compare(a.Hash().Bytes(), b.Hash().Bytes()) + if cmp != 0 { + return cmp + } + + return bytes.Compare(a.LeafBlob(), b.LeafBlob()) +} + +type differenceIterator struct { + a, b NodeIterator // Nodes returned are those in b - a. + eof bool // Indicates a has run out of elements + count int // Number of nodes scanned on either trie +} + +// NewDifferenceIterator constructs a NodeIterator that iterates over elements in b that +// are not in a. Returns the iterator, and a pointer to an integer recording the number +// of nodes seen. +func NewDifferenceIterator(a, b NodeIterator) (NodeIterator, *int) { + a.Next(true) + it := &differenceIterator{ + a: a, + b: b, + } + return it, &it.count +} + +func (it *differenceIterator) Hash() common.Hash { + return it.b.Hash() +} + +func (it *differenceIterator) Parent() common.Hash { + return it.b.Parent() +} + +func (it *differenceIterator) Leaf() bool { + return it.b.Leaf() +} + +func (it *differenceIterator) LeafBlob() []byte { + return it.b.LeafBlob() +} + +func (it *differenceIterator) Path() []byte { + return it.b.Path() +} + +func (it *differenceIterator) Next(bool) bool { + // Invariants: + // - We always advance at least one element in b. + // - At the start of this function, a's path is lexically greater than b's. + if !it.b.Next(true) { + return false + } + it.count += 1 + + if it.eof { + // a has reached eof, so we just return all elements from b + return true + } + + for { + switch compareNodes(it.a, it.b) { + case -1: + // b jumped past a; advance a + if !it.a.Next(true) { + it.eof = true + return true + } + it.count += 1 + case 1: + // b is before a + return true + case 0: + // a and b are identical; skip this whole subtree if the nodes have hashes + hasHash := it.a.Hash() == common.Hash{} + if !it.b.Next(hasHash) { + return false + } + it.count += 1 + if !it.a.Next(hasHash) { + it.eof = true + return true + } + it.count += 1 + } + } +} + +func (it *differenceIterator) Error() error { + if err := it.a.Error(); err != nil { + return err + } + return it.b.Error() +} + +type nodeIteratorHeap []NodeIterator + +func (h nodeIteratorHeap) Len() int { return len(h) } +func (h nodeIteratorHeap) Less(i, j int) bool { return compareNodes(h[i], h[j]) < 0 } +func (h nodeIteratorHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *nodeIteratorHeap) Push(x interface{}) { *h = append(*h, x.(NodeIterator)) } +func (h *nodeIteratorHeap) Pop() interface{} { + n := len(*h) + x := (*h)[n-1] + *h = (*h)[0 : n-1] + return x +} + +type unionIterator struct { + items *nodeIteratorHeap // Nodes returned are the union of the ones in these iterators + count int // Number of nodes scanned across all tries + err error // The error, if one has been encountered +} + +// NewUnionIterator constructs a NodeIterator that iterates over elements in the union +// of the provided NodeIterators. Returns the iterator, and a pointer to an integer +// recording the number of nodes visited. +func NewUnionIterator(iters []NodeIterator) (NodeIterator, *int) { + h := make(nodeIteratorHeap, len(iters)) + copy(h, iters) + heap.Init(&h) + + ui := &unionIterator{ + items: &h, + } + return ui, &ui.count +} + +func (it *unionIterator) Hash() common.Hash { + return (*it.items)[0].Hash() +} + +func (it *unionIterator) Parent() common.Hash { + return (*it.items)[0].Parent() +} + +func (it *unionIterator) Leaf() bool { + return (*it.items)[0].Leaf() +} + +func (it *unionIterator) LeafBlob() []byte { + return (*it.items)[0].LeafBlob() +} + +func (it *unionIterator) Path() []byte { + return (*it.items)[0].Path() +} + +// Next returns the next node in the union of tries being iterated over. +// +// It does this by maintaining a heap of iterators, sorted by the iteration +// order of their next elements, with one entry for each source trie. Each +// time Next() is called, it takes the least element from the heap to return, +// advancing any other iterators that also point to that same element. These +// iterators are called with descend=false, since we know that any nodes under +// these nodes will also be duplicates, found in the currently selected iterator. +// Whenever an iterator is advanced, it is pushed back into the heap if it still +// has elements remaining. +// +// In the case that descend=false - eg, we're asked to ignore all subnodes of the +// current node - we also advance any iterators in the heap that have the current +// path as a prefix. +func (it *unionIterator) Next(descend bool) bool { + if len(*it.items) == 0 { + return false + } + + // Get the next key from the union + least := heap.Pop(it.items).(NodeIterator) + + // Skip over other nodes as long as they're identical, or, if we're not descending, as + // long as they have the same prefix as the current node. + for len(*it.items) > 0 && ((!descend && bytes.HasPrefix((*it.items)[0].Path(), least.Path())) || compareNodes(least, (*it.items)[0]) == 0) { + skipped := heap.Pop(it.items).(NodeIterator) + // Skip the whole subtree if the nodes have hashes; otherwise just skip this node + if skipped.Next(skipped.Hash() == common.Hash{}) { + it.count += 1 + // If there are more elements, push the iterator back on the heap + heap.Push(it.items, skipped) + } + } + + if least.Next(descend) { + it.count += 1 + heap.Push(it.items, least) + } + + return len(*it.items) > 0 +} + +func (it *unionIterator) Error() error { + for i := 0; i < len(*it.items); i++ { + if err := (*it.items)[i].Error(); err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/node.go b/vendor/github.com/ethereum/go-ethereum/trie/node.go new file mode 100644 index 00000000..a7697fc0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/node.go @@ -0,0 +1,224 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +import ( + "fmt" + "io" + "strings" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" +) + +var indices = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "[17]"} + +type node interface { + fstring(string) string + cache() (hashNode, bool) + canUnload(cachegen, cachelimit uint16) bool +} + +type ( + fullNode struct { + Children [17]node // Actual trie node data to encode/decode (needs custom encoder) + flags nodeFlag + } + shortNode struct { + Key []byte + Val node + flags nodeFlag + } + hashNode []byte + valueNode []byte +) + +// EncodeRLP encodes a full node into the consensus RLP format. +func (n *fullNode) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, n.Children) +} + +func (n *fullNode) copy() *fullNode { copy := *n; return © } +func (n *shortNode) copy() *shortNode { copy := *n; return © } + +// nodeFlag contains caching-related metadata about a node. +type nodeFlag struct { + hash hashNode // cached hash of the node (may be nil) + gen uint16 // cache generation counter + dirty bool // whether the node has changes that must be written to the database +} + +// canUnload tells whether a node can be unloaded. +func (n *nodeFlag) canUnload(cachegen, cachelimit uint16) bool { + return !n.dirty && cachegen-n.gen >= cachelimit +} + +func (n *fullNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) } +func (n *shortNode) canUnload(gen, limit uint16) bool { return n.flags.canUnload(gen, limit) } +func (n hashNode) canUnload(uint16, uint16) bool { return false } +func (n valueNode) canUnload(uint16, uint16) bool { return false } + +func (n *fullNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty } +func (n *shortNode) cache() (hashNode, bool) { return n.flags.hash, n.flags.dirty } +func (n hashNode) cache() (hashNode, bool) { return nil, true } +func (n valueNode) cache() (hashNode, bool) { return nil, true } + +// Pretty printing. +func (n *fullNode) String() string { return n.fstring("") } +func (n *shortNode) String() string { return n.fstring("") } +func (n hashNode) String() string { return n.fstring("") } +func (n valueNode) String() string { return n.fstring("") } + +func (n *fullNode) fstring(ind string) string { + resp := fmt.Sprintf("[\n%s ", ind) + for i, node := range n.Children { + if node == nil { + resp += fmt.Sprintf("%s: ", indices[i]) + } else { + resp += fmt.Sprintf("%s: %v", indices[i], node.fstring(ind+" ")) + } + } + return resp + fmt.Sprintf("\n%s] ", ind) +} +func (n *shortNode) fstring(ind string) string { + return fmt.Sprintf("{%x: %v} ", n.Key, n.Val.fstring(ind+" ")) +} +func (n hashNode) fstring(ind string) string { + return fmt.Sprintf("<%x> ", []byte(n)) +} +func (n valueNode) fstring(ind string) string { + return fmt.Sprintf("%x ", []byte(n)) +} + +func mustDecodeNode(hash, buf []byte, cachegen uint16) node { + n, err := decodeNode(hash, buf, cachegen) + if err != nil { + panic(fmt.Sprintf("node %x: %v", hash, err)) + } + return n +} + +// decodeNode parses the RLP encoding of a trie node. +func decodeNode(hash, buf []byte, cachegen uint16) (node, error) { + if len(buf) == 0 { + return nil, io.ErrUnexpectedEOF + } + elems, _, err := rlp.SplitList(buf) + if err != nil { + return nil, fmt.Errorf("decode error: %v", err) + } + switch c, _ := rlp.CountValues(elems); c { + case 2: + n, err := decodeShort(hash, buf, elems, cachegen) + return n, wrapError(err, "short") + case 17: + n, err := decodeFull(hash, buf, elems, cachegen) + return n, wrapError(err, "full") + default: + return nil, fmt.Errorf("invalid number of list elements: %v", c) + } +} + +func decodeShort(hash, buf, elems []byte, cachegen uint16) (node, error) { + kbuf, rest, err := rlp.SplitString(elems) + if err != nil { + return nil, err + } + flag := nodeFlag{hash: hash, gen: cachegen} + key := compactToHex(kbuf) + if hasTerm(key) { + // value node + val, _, err := rlp.SplitString(rest) + if err != nil { + return nil, fmt.Errorf("invalid value node: %v", err) + } + return &shortNode{key, append(valueNode{}, val...), flag}, nil + } + r, _, err := decodeRef(rest, cachegen) + if err != nil { + return nil, wrapError(err, "val") + } + return &shortNode{key, r, flag}, nil +} + +func decodeFull(hash, buf, elems []byte, cachegen uint16) (*fullNode, error) { + n := &fullNode{flags: nodeFlag{hash: hash, gen: cachegen}} + for i := 0; i < 16; i++ { + cld, rest, err := decodeRef(elems, cachegen) + if err != nil { + return n, wrapError(err, fmt.Sprintf("[%d]", i)) + } + n.Children[i], elems = cld, rest + } + val, _, err := rlp.SplitString(elems) + if err != nil { + return n, err + } + if len(val) > 0 { + n.Children[16] = append(valueNode{}, val...) + } + return n, nil +} + +const hashLen = len(common.Hash{}) + +func decodeRef(buf []byte, cachegen uint16) (node, []byte, error) { + kind, val, rest, err := rlp.Split(buf) + if err != nil { + return nil, buf, err + } + switch { + case kind == rlp.List: + // 'embedded' node reference. The encoding must be smaller + // than a hash in order to be valid. + if size := len(buf) - len(rest); size > hashLen { + err := fmt.Errorf("oversized embedded node (size is %d bytes, want size < %d)", size, hashLen) + return nil, buf, err + } + n, err := decodeNode(nil, buf, cachegen) + return n, rest, err + case kind == rlp.String && len(val) == 0: + // empty node + return nil, rest, nil + case kind == rlp.String && len(val) == 32: + return append(hashNode{}, val...), rest, nil + default: + return nil, nil, fmt.Errorf("invalid RLP string size %d (want 0 or 32)", len(val)) + } +} + +// wraps a decoding error with information about the path to the +// invalid child node (for debugging encoding issues). +type decodeError struct { + what error + stack []string +} + +func wrapError(err error, ctx string) error { + if err == nil { + return nil + } + if decErr, ok := err.(*decodeError); ok { + decErr.stack = append(decErr.stack, ctx) + return decErr + } + return &decodeError{err, []string{ctx}} +} + +func (err *decodeError) Error() string { + return fmt.Sprintf("%v (decode path: %s)", err.what, strings.Join(err.stack, "<-")) +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/proof.go b/vendor/github.com/ethereum/go-ethereum/trie/proof.go new file mode 100644 index 00000000..fb7734b8 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/proof.go @@ -0,0 +1,148 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +import ( + "bytes" + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto/sha3" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" +) + +// Prove constructs a merkle proof for key. The result contains all +// encoded nodes on the path to the value at key. The value itself is +// also included in the last node and can be retrieved by verifying +// the proof. +// +// If the trie does not contain a value for key, the returned proof +// contains all nodes of the longest existing prefix of the key +// (at least the root node), ending with the node that proves the +// absence of the key. +func (t *Trie) Prove(key []byte) []rlp.RawValue { + // Collect all nodes on the path to key. + key = keybytesToHex(key) + nodes := []node{} + tn := t.root + for len(key) > 0 && tn != nil { + switch n := tn.(type) { + case *shortNode: + if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) { + // The trie doesn't contain the key. + tn = nil + } else { + tn = n.Val + key = key[len(n.Key):] + } + nodes = append(nodes, n) + case *fullNode: + tn = n.Children[key[0]] + key = key[1:] + nodes = append(nodes, n) + case hashNode: + var err error + tn, err = t.resolveHash(n, nil, nil) + if err != nil { + log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) + return nil + } + default: + panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) + } + } + hasher := newHasher(0, 0) + proof := make([]rlp.RawValue, 0, len(nodes)) + for i, n := range nodes { + // Don't bother checking for errors here since hasher panics + // if encoding doesn't work and we're not writing to any database. + n, _, _ = hasher.hashChildren(n, nil) + hn, _ := hasher.store(n, nil, false) + if _, ok := hn.(hashNode); ok || i == 0 { + // If the node's database encoding is a hash (or is the + // root node), it becomes a proof element. + enc, _ := rlp.EncodeToBytes(n) + proof = append(proof, enc) + } + } + return proof +} + +// VerifyProof checks merkle proofs. The given proof must contain the +// value for key in a trie with the given root hash. VerifyProof +// returns an error if the proof contains invalid trie nodes or the +// wrong value. +func VerifyProof(rootHash common.Hash, key []byte, proof []rlp.RawValue) (value []byte, err error) { + key = keybytesToHex(key) + sha := sha3.NewKeccak256() + wantHash := rootHash.Bytes() + for i, buf := range proof { + sha.Reset() + sha.Write(buf) + if !bytes.Equal(sha.Sum(nil), wantHash) { + return nil, fmt.Errorf("bad proof node %d: hash mismatch", i) + } + n, err := decodeNode(wantHash, buf, 0) + if err != nil { + return nil, fmt.Errorf("bad proof node %d: %v", i, err) + } + keyrest, cld := get(n, key) + switch cld := cld.(type) { + case nil: + if i != len(proof)-1 { + return nil, fmt.Errorf("key mismatch at proof node %d", i) + } else { + // The trie doesn't contain the key. + return nil, nil + } + case hashNode: + key = keyrest + wantHash = cld + case valueNode: + if i != len(proof)-1 { + return nil, errors.New("additional nodes at end of proof") + } + return cld, nil + } + } + return nil, errors.New("unexpected end of proof") +} + +func get(tn node, key []byte) ([]byte, node) { + for len(key) > 0 { + switch n := tn.(type) { + case *shortNode: + if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) { + return nil, nil + } + tn = n.Val + key = key[len(n.Key):] + case *fullNode: + tn = n.Children[key[0]] + key = key[1:] + case hashNode: + return key, n + case nil: + return key, nil + default: + panic(fmt.Sprintf("%T: invalid node: %v", tn, tn)) + } + } + return nil, tn.(valueNode) +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go b/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go new file mode 100644 index 00000000..37d1d4b0 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/secure_trie.go @@ -0,0 +1,213 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" +) + +var secureKeyPrefix = []byte("secure-key-") + +const secureKeyLength = 11 + 32 // Length of the above prefix + 32byte hash + +// SecureTrie wraps a trie with key hashing. In a secure trie, all +// access operations hash the key using keccak256. This prevents +// calling code from creating long chains of nodes that +// increase the access time. +// +// Contrary to a regular trie, a SecureTrie can only be created with +// New and must have an attached database. The database also stores +// the preimage of each key. +// +// SecureTrie is not safe for concurrent use. +type SecureTrie struct { + trie Trie + hashKeyBuf [secureKeyLength]byte + secKeyBuf [200]byte + secKeyCache map[string][]byte + secKeyCacheOwner *SecureTrie // Pointer to self, replace the key cache on mismatch +} + +// NewSecure creates a trie with an existing root node from db. +// +// If root is the zero hash or the sha3 hash of an empty string, the +// trie is initially empty. Otherwise, New will panic if db is nil +// and returns MissingNodeError if the root node cannot be found. +// +// Accessing the trie loads nodes from db on demand. +// Loaded nodes are kept around until their 'cache generation' expires. +// A new cache generation is created by each call to Commit. +// cachelimit sets the number of past cache generations to keep. +func NewSecure(root common.Hash, db Database, cachelimit uint16) (*SecureTrie, error) { + if db == nil { + panic("NewSecure called with nil database") + } + trie, err := New(root, db) + if err != nil { + return nil, err + } + trie.SetCacheLimit(cachelimit) + return &SecureTrie{trie: *trie}, nil +} + +// Get returns the value for key stored in the trie. +// The value bytes must not be modified by the caller. +func (t *SecureTrie) Get(key []byte) []byte { + res, err := t.TryGet(key) + if err != nil { + log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) + } + return res +} + +// TryGet returns the value for key stored in the trie. +// The value bytes must not be modified by the caller. +// If a node was not found in the database, a MissingNodeError is returned. +func (t *SecureTrie) TryGet(key []byte) ([]byte, error) { + return t.trie.TryGet(t.hashKey(key)) +} + +// Update associates key with value in the trie. Subsequent calls to +// Get will return value. If value has length zero, any existing value +// is deleted from the trie and calls to Get will return nil. +// +// The value bytes must not be modified by the caller while they are +// stored in the trie. +func (t *SecureTrie) Update(key, value []byte) { + if err := t.TryUpdate(key, value); err != nil { + log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) + } +} + +// TryUpdate associates key with value in the trie. Subsequent calls to +// Get will return value. If value has length zero, any existing value +// is deleted from the trie and calls to Get will return nil. +// +// The value bytes must not be modified by the caller while they are +// stored in the trie. +// +// If a node was not found in the database, a MissingNodeError is returned. +func (t *SecureTrie) TryUpdate(key, value []byte) error { + hk := t.hashKey(key) + err := t.trie.TryUpdate(hk, value) + if err != nil { + return err + } + t.getSecKeyCache()[string(hk)] = common.CopyBytes(key) + return nil +} + +// Delete removes any existing value for key from the trie. +func (t *SecureTrie) Delete(key []byte) { + if err := t.TryDelete(key); err != nil { + log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) + } +} + +// TryDelete removes any existing value for key from the trie. +// If a node was not found in the database, a MissingNodeError is returned. +func (t *SecureTrie) TryDelete(key []byte) error { + hk := t.hashKey(key) + delete(t.getSecKeyCache(), string(hk)) + return t.trie.TryDelete(hk) +} + +// GetKey returns the sha3 preimage of a hashed key that was +// previously used to store a value. +func (t *SecureTrie) GetKey(shaKey []byte) []byte { + if key, ok := t.getSecKeyCache()[string(shaKey)]; ok { + return key + } + key, _ := t.trie.db.Get(t.secKey(shaKey)) + return key +} + +// Commit writes all nodes and the secure hash pre-images to the trie's database. +// Nodes are stored with their sha3 hash as the key. +// +// Committing flushes nodes from memory. Subsequent Get calls will load nodes +// from the database. +func (t *SecureTrie) Commit() (root common.Hash, err error) { + return t.CommitTo(t.trie.db) +} + +func (t *SecureTrie) Hash() common.Hash { + return t.trie.Hash() +} + +func (t *SecureTrie) Root() []byte { + return t.trie.Root() +} + +// NodeIterator returns an iterator that returns nodes of the underlying trie. Iteration +// starts at the key after the given start key. +func (t *SecureTrie) NodeIterator(start []byte) NodeIterator { + return t.trie.NodeIterator(start) +} + +// CommitTo writes all nodes and the secure hash pre-images to the given database. +// Nodes are stored with their sha3 hash as the key. +// +// Committing flushes nodes from memory. Subsequent Get calls will load nodes from +// the trie's database. Calling code must ensure that the changes made to db are +// written back to the trie's attached database before using the trie. +func (t *SecureTrie) CommitTo(db DatabaseWriter) (root common.Hash, err error) { + if len(t.getSecKeyCache()) > 0 { + for hk, key := range t.secKeyCache { + if err := db.Put(t.secKey([]byte(hk)), key); err != nil { + return common.Hash{}, err + } + } + t.secKeyCache = make(map[string][]byte) + } + return t.trie.CommitTo(db) +} + +// secKey returns the database key for the preimage of key, as an ephemeral buffer. +// The caller must not hold onto the return value because it will become +// invalid on the next call to hashKey or secKey. +func (t *SecureTrie) secKey(key []byte) []byte { + buf := append(t.secKeyBuf[:0], secureKeyPrefix...) + buf = append(buf, key...) + return buf +} + +// hashKey returns the hash of key as an ephemeral buffer. +// The caller must not hold onto the return value because it will become +// invalid on the next call to hashKey or secKey. +func (t *SecureTrie) hashKey(key []byte) []byte { + h := newHasher(0, 0) + h.sha.Reset() + h.sha.Write(key) + buf := h.sha.Sum(t.hashKeyBuf[:0]) + returnHasherToPool(h) + return buf +} + +// getSecKeyCache returns the current secure key cache, creating a new one if +// ownership changed (i.e. the current secure trie is a copy of another owning +// the actual cache). +func (t *SecureTrie) getSecKeyCache() map[string][]byte { + if t != t.secKeyCacheOwner { + t.secKeyCacheOwner = t + t.secKeyCache = make(map[string][]byte) + } + return t.secKeyCache +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/sync.go b/vendor/github.com/ethereum/go-ethereum/trie/sync.go new file mode 100644 index 00000000..16850139 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/sync.go @@ -0,0 +1,285 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package trie + +import ( + "errors" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "gopkg.in/karalabe/cookiejar.v2/collections/prque" +) + +// ErrNotRequested is returned by the trie sync when it's requested to process a +// node it did not request. +var ErrNotRequested = errors.New("not requested") + +// request represents a scheduled or already in-flight state retrieval request. +type request struct { + hash common.Hash // Hash of the node data content to retrieve + data []byte // Data content of the node, cached until all subtrees complete + raw bool // Whether this is a raw entry (code) or a trie node + + parents []*request // Parent state nodes referencing this entry (notify all upon completion) + depth int // Depth level within the trie the node is located to prioritise DFS + deps int // Number of dependencies before allowed to commit this node + + callback TrieSyncLeafCallback // Callback to invoke if a leaf node it reached on this branch +} + +// SyncResult is a simple list to return missing nodes along with their request +// hashes. +type SyncResult struct { + Hash common.Hash // Hash of the originally unknown trie node + Data []byte // Data content of the retrieved node +} + +// TrieSyncLeafCallback is a callback type invoked when a trie sync reaches a +// leaf node. It's used by state syncing to check if the leaf node requires some +// further data syncing. +type TrieSyncLeafCallback func(leaf []byte, parent common.Hash) error + +// TrieSync is the main state trie synchronisation scheduler, which provides yet +// unknown trie hashes to retrieve, accepts node data associated with said hashes +// and reconstructs the trie step by step until all is done. +type TrieSync struct { + database DatabaseReader + requests map[common.Hash]*request // Pending requests pertaining to a key hash + queue *prque.Prque // Priority queue with the pending requests +} + +// NewTrieSync creates a new trie data download scheduler. +func NewTrieSync(root common.Hash, database DatabaseReader, callback TrieSyncLeafCallback) *TrieSync { + ts := &TrieSync{ + database: database, + requests: make(map[common.Hash]*request), + queue: prque.New(), + } + ts.AddSubTrie(root, 0, common.Hash{}, callback) + return ts +} + +// AddSubTrie registers a new trie to the sync code, rooted at the designated parent. +func (s *TrieSync) AddSubTrie(root common.Hash, depth int, parent common.Hash, callback TrieSyncLeafCallback) { + // Short circuit if the trie is empty or already known + if root == emptyRoot { + return + } + key := root.Bytes() + blob, _ := s.database.Get(key) + if local, err := decodeNode(key, blob, 0); local != nil && err == nil { + return + } + // Assemble the new sub-trie sync request + req := &request{ + hash: root, + depth: depth, + callback: callback, + } + // If this sub-trie has a designated parent, link them together + if parent != (common.Hash{}) { + ancestor := s.requests[parent] + if ancestor == nil { + panic(fmt.Sprintf("sub-trie ancestor not found: %x", parent)) + } + ancestor.deps++ + req.parents = append(req.parents, ancestor) + } + s.schedule(req) +} + +// AddRawEntry schedules the direct retrieval of a state entry that should not be +// interpreted as a trie node, but rather accepted and stored into the database +// as is. This method's goal is to support misc state metadata retrievals (e.g. +// contract code). +func (s *TrieSync) AddRawEntry(hash common.Hash, depth int, parent common.Hash) { + // Short circuit if the entry is empty or already known + if hash == emptyState { + return + } + if blob, _ := s.database.Get(hash.Bytes()); blob != nil { + return + } + // Assemble the new sub-trie sync request + req := &request{ + hash: hash, + raw: true, + depth: depth, + } + // If this sub-trie has a designated parent, link them together + if parent != (common.Hash{}) { + ancestor := s.requests[parent] + if ancestor == nil { + panic(fmt.Sprintf("raw-entry ancestor not found: %x", parent)) + } + ancestor.deps++ + req.parents = append(req.parents, ancestor) + } + s.schedule(req) +} + +// Missing retrieves the known missing nodes from the trie for retrieval. +func (s *TrieSync) Missing(max int) []common.Hash { + requests := []common.Hash{} + for !s.queue.Empty() && (max == 0 || len(requests) < max) { + requests = append(requests, s.queue.PopItem().(common.Hash)) + } + return requests +} + +// Process injects a batch of retrieved trie nodes data, returning if something +// was committed to the database and also the index of an entry if processing of +// it failed. +func (s *TrieSync) Process(results []SyncResult, dbw DatabaseWriter) (bool, int, error) { + committed := false + + for i, item := range results { + // If the item was not requested, bail out + request := s.requests[item.Hash] + if request == nil { + return committed, i, ErrNotRequested + } + // If the item is a raw entry request, commit directly + if request.raw { + request.data = item.Data + s.commit(request, dbw) + committed = true + continue + } + // Decode the node data content and update the request + node, err := decodeNode(item.Hash[:], item.Data, 0) + if err != nil { + return committed, i, err + } + request.data = item.Data + + // Create and schedule a request for all the children nodes + requests, err := s.children(request, node) + if err != nil { + return committed, i, err + } + if len(requests) == 0 && request.deps == 0 { + s.commit(request, dbw) + committed = true + continue + } + request.deps += len(requests) + for _, child := range requests { + s.schedule(child) + } + } + return committed, 0, nil +} + +// Pending returns the number of state entries currently pending for download. +func (s *TrieSync) Pending() int { + return len(s.requests) +} + +// schedule inserts a new state retrieval request into the fetch queue. If there +// is already a pending request for this node, the new request will be discarded +// and only a parent reference added to the old one. +func (s *TrieSync) schedule(req *request) { + // If we're already requesting this node, add a new reference and stop + if old, ok := s.requests[req.hash]; ok { + old.parents = append(old.parents, req.parents...) + return + } + // Schedule the request for future retrieval + s.queue.Push(req.hash, float32(req.depth)) + s.requests[req.hash] = req +} + +// children retrieves all the missing children of a state trie entry for future +// retrieval scheduling. +func (s *TrieSync) children(req *request, object node) ([]*request, error) { + // Gather all the children of the node, irrelevant whether known or not + type child struct { + node node + depth int + } + children := []child{} + + switch node := (object).(type) { + case *shortNode: + children = []child{{ + node: node.Val, + depth: req.depth + len(node.Key), + }} + case *fullNode: + for i := 0; i < 17; i++ { + if node.Children[i] != nil { + children = append(children, child{ + node: node.Children[i], + depth: req.depth + 1, + }) + } + } + default: + panic(fmt.Sprintf("unknown node: %+v", node)) + } + // Iterate over the children, and request all unknown ones + requests := make([]*request, 0, len(children)) + for _, child := range children { + // Notify any external watcher of a new key/value node + if req.callback != nil { + if node, ok := (child.node).(valueNode); ok { + if err := req.callback(node, req.hash); err != nil { + return nil, err + } + } + } + // If the child references another node, resolve or schedule + if node, ok := (child.node).(hashNode); ok { + // Try to resolve the node from the local database + blob, _ := s.database.Get(node) + if local, err := decodeNode(node[:], blob, 0); local != nil && err == nil { + continue + } + // Locally unknown node, schedule for retrieval + requests = append(requests, &request{ + hash: common.BytesToHash(node), + parents: []*request{req}, + depth: child.depth, + callback: req.callback, + }) + } + } + return requests, nil +} + +// commit finalizes a retrieval request and stores it into the database. If any +// of the referencing parent requests complete due to this commit, they are also +// committed themselves. +func (s *TrieSync) commit(req *request, dbw DatabaseWriter) (err error) { + // Write the node content to disk + if err := dbw.Put(req.hash[:], req.data); err != nil { + return err + } + delete(s.requests, req.hash) + + // Check all parents for completion + for _, parent := range req.parents { + parent.deps-- + if parent.deps == 0 { + if err := s.commit(parent, dbw); err != nil { + return err + } + } + } + return nil +} diff --git a/vendor/github.com/ethereum/go-ethereum/trie/trie.go b/vendor/github.com/ethereum/go-ethereum/trie/trie.go new file mode 100644 index 00000000..cbe49657 --- /dev/null +++ b/vendor/github.com/ethereum/go-ethereum/trie/trie.go @@ -0,0 +1,510 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package trie implements Merkle Patricia Tries. +package trie + +import ( + "bytes" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto/sha3" + "github.com/ethereum/go-ethereum/log" + "github.com/rcrowley/go-metrics" +) + +var ( + // This is the known root hash of an empty trie. + emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + // This is the known hash of an empty state trie entry. + emptyState common.Hash +) + +var ( + cacheMissCounter = metrics.NewRegisteredCounter("trie/cachemiss", nil) + cacheUnloadCounter = metrics.NewRegisteredCounter("trie/cacheunload", nil) +) + +// CacheMisses retrieves a global counter measuring the number of cache misses +// the trie had since process startup. This isn't useful for anything apart from +// trie debugging purposes. +func CacheMisses() int64 { + return cacheMissCounter.Count() +} + +// CacheUnloads retrieves a global counter measuring the number of cache unloads +// the trie did since process startup. This isn't useful for anything apart from +// trie debugging purposes. +func CacheUnloads() int64 { + return cacheUnloadCounter.Count() +} + +func init() { + sha3.NewKeccak256().Sum(emptyState[:0]) +} + +// Database must be implemented by backing stores for the trie. +type Database interface { + DatabaseReader + DatabaseWriter +} + +// DatabaseReader wraps the Get method of a backing store for the trie. +type DatabaseReader interface { + Get(key []byte) (value []byte, err error) +} + +// DatabaseWriter wraps the Put method of a backing store for the trie. +type DatabaseWriter interface { + // Put stores the mapping key->value in the database. + // Implementations must not hold onto the value bytes, the trie + // will reuse the slice across calls to Put. + Put(key, value []byte) error +} + +// Trie is a Merkle Patricia Trie. +// The zero value is an empty trie with no database. +// Use New to create a trie that sits on top of a database. +// +// Trie is not safe for concurrent use. +type Trie struct { + root node + db Database + originalRoot common.Hash + + // Cache generation values. + // cachegen increases by one with each commit operation. + // new nodes are tagged with the current generation and unloaded + // when their generation is older than than cachegen-cachelimit. + cachegen, cachelimit uint16 +} + +// SetCacheLimit sets the number of 'cache generations' to keep. +// A cache generation is created by a call to Commit. +func (t *Trie) SetCacheLimit(l uint16) { + t.cachelimit = l +} + +// newFlag returns the cache flag value for a newly created node. +func (t *Trie) newFlag() nodeFlag { + return nodeFlag{dirty: true, gen: t.cachegen} +} + +// New creates a trie with an existing root node from db. +// +// If root is the zero hash or the sha3 hash of an empty string, the +// trie is initially empty and does not require a database. Otherwise, +// New will panic if db is nil and returns a MissingNodeError if root does +// not exist in the database. Accessing the trie loads nodes from db on demand. +func New(root common.Hash, db Database) (*Trie, error) { + trie := &Trie{db: db, originalRoot: root} + if (root != common.Hash{}) && root != emptyRoot { + if db == nil { + panic("trie.New: cannot use existing root without a database") + } + rootnode, err := trie.resolveHash(root[:], nil, nil) + if err != nil { + return nil, err + } + trie.root = rootnode + } + return trie, nil +} + +// NodeIterator returns an iterator that returns nodes of the trie. Iteration starts at +// the key after the given start key. +func (t *Trie) NodeIterator(start []byte) NodeIterator { + return newNodeIterator(t, start) +} + +// Get returns the value for key stored in the trie. +// The value bytes must not be modified by the caller. +func (t *Trie) Get(key []byte) []byte { + res, err := t.TryGet(key) + if err != nil { + log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) + } + return res +} + +// TryGet returns the value for key stored in the trie. +// The value bytes must not be modified by the caller. +// If a node was not found in the database, a MissingNodeError is returned. +func (t *Trie) TryGet(key []byte) ([]byte, error) { + key = keybytesToHex(key) + value, newroot, didResolve, err := t.tryGet(t.root, key, 0) + if err == nil && didResolve { + t.root = newroot + } + return value, err +} + +func (t *Trie) tryGet(origNode node, key []byte, pos int) (value []byte, newnode node, didResolve bool, err error) { + switch n := (origNode).(type) { + case nil: + return nil, nil, false, nil + case valueNode: + return n, n, false, nil + case *shortNode: + if len(key)-pos < len(n.Key) || !bytes.Equal(n.Key, key[pos:pos+len(n.Key)]) { + // key not found in trie + return nil, n, false, nil + } + value, newnode, didResolve, err = t.tryGet(n.Val, key, pos+len(n.Key)) + if err == nil && didResolve { + n = n.copy() + n.Val = newnode + n.flags.gen = t.cachegen + } + return value, n, didResolve, err + case *fullNode: + value, newnode, didResolve, err = t.tryGet(n.Children[key[pos]], key, pos+1) + if err == nil && didResolve { + n = n.copy() + n.flags.gen = t.cachegen + n.Children[key[pos]] = newnode + } + return value, n, didResolve, err + case hashNode: + child, err := t.resolveHash(n, key[:pos], key[pos:]) + if err != nil { + return nil, n, true, err + } + value, newnode, _, err := t.tryGet(child, key, pos) + return value, newnode, true, err + default: + panic(fmt.Sprintf("%T: invalid node: %v", origNode, origNode)) + } +} + +// Update associates key with value in the trie. Subsequent calls to +// Get will return value. If value has length zero, any existing value +// is deleted from the trie and calls to Get will return nil. +// +// The value bytes must not be modified by the caller while they are +// stored in the trie. +func (t *Trie) Update(key, value []byte) { + if err := t.TryUpdate(key, value); err != nil { + log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) + } +} + +// TryUpdate associates key with value in the trie. Subsequent calls to +// Get will return value. If value has length zero, any existing value +// is deleted from the trie and calls to Get will return nil. +// +// The value bytes must not be modified by the caller while they are +// stored in the trie. +// +// If a node was not found in the database, a MissingNodeError is returned. +func (t *Trie) TryUpdate(key, value []byte) error { + k := keybytesToHex(key) + if len(value) != 0 { + _, n, err := t.insert(t.root, nil, k, valueNode(value)) + if err != nil { + return err + } + t.root = n + } else { + _, n, err := t.delete(t.root, nil, k) + if err != nil { + return err + } + t.root = n + } + return nil +} + +func (t *Trie) insert(n node, prefix, key []byte, value node) (bool, node, error) { + if len(key) == 0 { + if v, ok := n.(valueNode); ok { + return !bytes.Equal(v, value.(valueNode)), value, nil + } + return true, value, nil + } + switch n := n.(type) { + case *shortNode: + matchlen := prefixLen(key, n.Key) + // If the whole key matches, keep this short node as is + // and only update the value. + if matchlen == len(n.Key) { + dirty, nn, err := t.insert(n.Val, append(prefix, key[:matchlen]...), key[matchlen:], value) + if !dirty || err != nil { + return false, n, err + } + return true, &shortNode{n.Key, nn, t.newFlag()}, nil + } + // Otherwise branch out at the index where they differ. + branch := &fullNode{flags: t.newFlag()} + var err error + _, branch.Children[n.Key[matchlen]], err = t.insert(nil, append(prefix, n.Key[:matchlen+1]...), n.Key[matchlen+1:], n.Val) + if err != nil { + return false, nil, err + } + _, branch.Children[key[matchlen]], err = t.insert(nil, append(prefix, key[:matchlen+1]...), key[matchlen+1:], value) + if err != nil { + return false, nil, err + } + // Replace this shortNode with the branch if it occurs at index 0. + if matchlen == 0 { + return true, branch, nil + } + // Otherwise, replace it with a short node leading up to the branch. + return true, &shortNode{key[:matchlen], branch, t.newFlag()}, nil + + case *fullNode: + dirty, nn, err := t.insert(n.Children[key[0]], append(prefix, key[0]), key[1:], value) + if !dirty || err != nil { + return false, n, err + } + n = n.copy() + n.flags = t.newFlag() + n.Children[key[0]] = nn + return true, n, nil + + case nil: + return true, &shortNode{key, value, t.newFlag()}, nil + + case hashNode: + // We've hit a part of the trie that isn't loaded yet. Load + // the node and insert into it. This leaves all child nodes on + // the path to the value in the trie. + rn, err := t.resolveHash(n, prefix, key) + if err != nil { + return false, nil, err + } + dirty, nn, err := t.insert(rn, prefix, key, value) + if !dirty || err != nil { + return false, rn, err + } + return true, nn, nil + + default: + panic(fmt.Sprintf("%T: invalid node: %v", n, n)) + } +} + +// Delete removes any existing value for key from the trie. +func (t *Trie) Delete(key []byte) { + if err := t.TryDelete(key); err != nil { + log.Error(fmt.Sprintf("Unhandled trie error: %v", err)) + } +} + +// TryDelete removes any existing value for key from the trie. +// If a node was not found in the database, a MissingNodeError is returned. +func (t *Trie) TryDelete(key []byte) error { + k := keybytesToHex(key) + _, n, err := t.delete(t.root, nil, k) + if err != nil { + return err + } + t.root = n + return nil +} + +// delete returns the new root of the trie with key deleted. +// It reduces the trie to minimal form by simplifying +// nodes on the way up after deleting recursively. +func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) { + switch n := n.(type) { + case *shortNode: + matchlen := prefixLen(key, n.Key) + if matchlen < len(n.Key) { + return false, n, nil // don't replace n on mismatch + } + if matchlen == len(key) { + return true, nil, nil // remove n entirely for whole matches + } + // The key is longer than n.Key. Remove the remaining suffix + // from the subtrie. Child can never be nil here since the + // subtrie must contain at least two other values with keys + // longer than n.Key. + dirty, child, err := t.delete(n.Val, append(prefix, key[:len(n.Key)]...), key[len(n.Key):]) + if !dirty || err != nil { + return false, n, err + } + switch child := child.(type) { + case *shortNode: + // Deleting from the subtrie reduced it to another + // short node. Merge the nodes to avoid creating a + // shortNode{..., shortNode{...}}. Use concat (which + // always creates a new slice) instead of append to + // avoid modifying n.Key since it might be shared with + // other nodes. + return true, &shortNode{concat(n.Key, child.Key...), child.Val, t.newFlag()}, nil + default: + return true, &shortNode{n.Key, child, t.newFlag()}, nil + } + + case *fullNode: + dirty, nn, err := t.delete(n.Children[key[0]], append(prefix, key[0]), key[1:]) + if !dirty || err != nil { + return false, n, err + } + n = n.copy() + n.flags = t.newFlag() + n.Children[key[0]] = nn + + // Check how many non-nil entries are left after deleting and + // reduce the full node to a short node if only one entry is + // left. Since n must've contained at least two children + // before deletion (otherwise it would not be a full node) n + // can never be reduced to nil. + // + // When the loop is done, pos contains the index of the single + // value that is left in n or -2 if n contains at least two + // values. + pos := -1 + for i, cld := range n.Children { + if cld != nil { + if pos == -1 { + pos = i + } else { + pos = -2 + break + } + } + } + if pos >= 0 { + if pos != 16 { + // If the remaining entry is a short node, it replaces + // n and its key gets the missing nibble tacked to the + // front. This avoids creating an invalid + // shortNode{..., shortNode{...}}. Since the entry + // might not be loaded yet, resolve it just for this + // check. + cnode, err := t.resolve(n.Children[pos], prefix, []byte{byte(pos)}) + if err != nil { + return false, nil, err + } + if cnode, ok := cnode.(*shortNode); ok { + k := append([]byte{byte(pos)}, cnode.Key...) + return true, &shortNode{k, cnode.Val, t.newFlag()}, nil + } + } + // Otherwise, n is replaced by a one-nibble short node + // containing the child. + return true, &shortNode{[]byte{byte(pos)}, n.Children[pos], t.newFlag()}, nil + } + // n still contains at least two values and cannot be reduced. + return true, n, nil + + case valueNode: + return true, nil, nil + + case nil: + return false, nil, nil + + case hashNode: + // We've hit a part of the trie that isn't loaded yet. Load + // the node and delete from it. This leaves all child nodes on + // the path to the value in the trie. + rn, err := t.resolveHash(n, prefix, key) + if err != nil { + return false, nil, err + } + dirty, nn, err := t.delete(rn, prefix, key) + if !dirty || err != nil { + return false, rn, err + } + return true, nn, nil + + default: + panic(fmt.Sprintf("%T: invalid node: %v (%v)", n, n, key)) + } +} + +func concat(s1 []byte, s2 ...byte) []byte { + r := make([]byte, len(s1)+len(s2)) + copy(r, s1) + copy(r[len(s1):], s2) + return r +} + +func (t *Trie) resolve(n node, prefix, suffix []byte) (node, error) { + if n, ok := n.(hashNode); ok { + return t.resolveHash(n, prefix, suffix) + } + return n, nil +} + +func (t *Trie) resolveHash(n hashNode, prefix, suffix []byte) (node, error) { + cacheMissCounter.Inc(1) + + enc, err := t.db.Get(n) + if err != nil || enc == nil { + return nil, &MissingNodeError{ + RootHash: t.originalRoot, + NodeHash: common.BytesToHash(n), + PrefixLen: len(prefix), + SuffixLen: len(suffix), + } + } + dec := mustDecodeNode(n, enc, t.cachegen) + return dec, nil +} + +// Root returns the root hash of the trie. +// Deprecated: use Hash instead. +func (t *Trie) Root() []byte { return t.Hash().Bytes() } + +// Hash returns the root hash of the trie. It does not write to the +// database and can be used even if the trie doesn't have one. +func (t *Trie) Hash() common.Hash { + hash, cached, _ := t.hashRoot(nil) + t.root = cached + return common.BytesToHash(hash.(hashNode)) +} + +// Commit writes all nodes to the trie's database. +// Nodes are stored with their sha3 hash as the key. +// +// Committing flushes nodes from memory. +// Subsequent Get calls will load nodes from the database. +func (t *Trie) Commit() (root common.Hash, err error) { + if t.db == nil { + panic("Commit called on trie with nil database") + } + return t.CommitTo(t.db) +} + +// CommitTo writes all nodes to the given database. +// Nodes are stored with their sha3 hash as the key. +// +// Committing flushes nodes from memory. Subsequent Get calls will +// load nodes from the trie's database. Calling code must ensure that +// the changes made to db are written back to the trie's attached +// database before using the trie. +func (t *Trie) CommitTo(db DatabaseWriter) (root common.Hash, err error) { + hash, cached, err := t.hashRoot(db) + if err != nil { + return (common.Hash{}), err + } + t.root = cached + t.cachegen++ + return common.BytesToHash(hash.(hashNode)), nil +} + +func (t *Trie) hashRoot(db DatabaseWriter) (node, node, error) { + if t.root == nil { + return hashNode(emptyRoot.Bytes()), nil, nil + } + h := newHasher(t.cachegen, t.cachelimit) + defer returnHasherToPool(h) + return h.hash(t.root, db, true) +} diff --git a/vendor/github.com/getamis/go-ethereum/COPYING b/vendor/github.com/getamis/go-ethereum/COPYING new file mode 100644 index 00000000..8d66e877 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/COPYING @@ -0,0 +1,619 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2014 The go-ethereum Authors. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. \ No newline at end of file diff --git a/vendor/github.com/getamis/go-ethereum/COPYING.LESSER b/vendor/github.com/getamis/go-ethereum/COPYING.LESSER new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/COPYING.LESSER @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/github.com/getamis/go-ethereum/common/big.go b/vendor/github.com/getamis/go-ethereum/common/big.go new file mode 100644 index 00000000..b552608b --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/big.go @@ -0,0 +1,30 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import "math/big" + +// Common big integers often used +var ( + Big1 = big.NewInt(1) + Big2 = big.NewInt(2) + Big3 = big.NewInt(3) + Big0 = big.NewInt(0) + Big32 = big.NewInt(32) + Big256 = big.NewInt(0xff) + Big257 = big.NewInt(257) +) diff --git a/vendor/github.com/getamis/go-ethereum/common/bytes.go b/vendor/github.com/getamis/go-ethereum/common/bytes.go new file mode 100644 index 00000000..c445968f --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/bytes.go @@ -0,0 +1,111 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package common contains various helper functions. +package common + +import ( + "encoding/hex" +) + +func ToHex(b []byte) string { + hex := Bytes2Hex(b) + // Prefer output of "0x0" instead of "0x" + if len(hex) == 0 { + hex = "0" + } + return "0x" + hex +} + +func FromHex(s string) []byte { + if len(s) > 1 { + if s[0:2] == "0x" || s[0:2] == "0X" { + s = s[2:] + } + if len(s)%2 == 1 { + s = "0" + s + } + return Hex2Bytes(s) + } + return nil +} + +// Copy bytes +// +// Returns an exact copy of the provided bytes +func CopyBytes(b []byte) (copiedBytes []byte) { + copiedBytes = make([]byte, len(b)) + copy(copiedBytes, b) + + return +} + +func HasHexPrefix(str string) bool { + l := len(str) + return l >= 2 && str[0:2] == "0x" +} + +func IsHex(str string) bool { + l := len(str) + return l >= 4 && l%2 == 0 && str[0:2] == "0x" +} + +func Bytes2Hex(d []byte) string { + return hex.EncodeToString(d) +} + +func Hex2Bytes(str string) []byte { + h, _ := hex.DecodeString(str) + + return h +} + +func Hex2BytesFixed(str string, flen int) []byte { + h, _ := hex.DecodeString(str) + if len(h) == flen { + return h + } else { + if len(h) > flen { + return h[len(h)-flen:] + } else { + hh := make([]byte, flen) + copy(hh[flen-len(h):flen], h[:]) + return hh + } + } +} + +func RightPadBytes(slice []byte, l int) []byte { + if l <= len(slice) { + return slice + } + + padded := make([]byte, l) + copy(padded, slice) + + return padded +} + +func LeftPadBytes(slice []byte, l int) []byte { + if l <= len(slice) { + return slice + } + + padded := make([]byte, l) + copy(padded[l-len(slice):], slice) + + return padded +} diff --git a/vendor/github.com/getamis/go-ethereum/common/debug.go b/vendor/github.com/getamis/go-ethereum/common/debug.go new file mode 100644 index 00000000..61acd8ce --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/debug.go @@ -0,0 +1,52 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "fmt" + "os" + "runtime" + "runtime/debug" + "strings" +) + +// Report gives off a warning requesting the user to submit an issue to the github tracker. +func Report(extra ...interface{}) { + fmt.Fprintln(os.Stderr, "You've encountered a sought after, hard to reproduce bug. Please report this to the developers <3 https://github.com/ethereum/go-ethereum/issues") + fmt.Fprintln(os.Stderr, extra...) + + _, file, line, _ := runtime.Caller(1) + fmt.Fprintf(os.Stderr, "%v:%v\n", file, line) + + debug.PrintStack() + + fmt.Fprintln(os.Stderr, "#### BUG! PLEASE REPORT ####") +} + +// PrintDepricationWarning prinst the given string in a box using fmt.Println. +func PrintDepricationWarning(str string) { + line := strings.Repeat("#", len(str)+4) + emptyLine := strings.Repeat(" ", len(str)) + fmt.Printf(` +%s +# %s # +# %s # +# %s # +%s + +`, line, emptyLine, str, emptyLine, line) +} diff --git a/vendor/github.com/getamis/go-ethereum/common/format.go b/vendor/github.com/getamis/go-ethereum/common/format.go new file mode 100644 index 00000000..fccc2996 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/format.go @@ -0,0 +1,40 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "fmt" + "regexp" + "strings" + "time" +) + +// PrettyDuration is a pretty printed version of a time.Duration value that cuts +// the unnecessary precision off from the formatted textual representation. +type PrettyDuration time.Duration + +var prettyDurationRe = regexp.MustCompile(`\.[0-9]+`) + +// String implements the Stringer interface, allowing pretty printing of duration +// values rounded to three decimals. +func (d PrettyDuration) String() string { + label := fmt.Sprintf("%v", time.Duration(d)) + if match := prettyDurationRe.FindString(label); len(match) > 4 { + label = strings.Replace(label, match, match[:4], 1) + } + return label +} diff --git a/vendor/github.com/getamis/go-ethereum/common/hexutil/hexutil.go b/vendor/github.com/getamis/go-ethereum/common/hexutil/hexutil.go new file mode 100644 index 00000000..6b128ae3 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/hexutil/hexutil.go @@ -0,0 +1,236 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +/* +Package hexutil implements hex encoding with 0x prefix. +This encoding is used by the Ethereum RPC API to transport binary data in JSON payloads. + +Encoding Rules + +All hex data must have prefix "0x". + +For byte slices, the hex data must be of even length. An empty byte slice +encodes as "0x". + +Integers are encoded using the least amount of digits (no leading zero digits). Their +encoding may be of uneven length. The number zero encodes as "0x0". +*/ +package hexutil + +import ( + "encoding/hex" + "errors" + "fmt" + "math/big" + "strconv" +) + +const uintBits = 32 << (uint64(^uint(0)) >> 63) + +var ( + ErrEmptyString = errors.New("empty hex string") + ErrMissingPrefix = errors.New("missing 0x prefix for hex data") + ErrSyntax = errors.New("invalid hex") + ErrEmptyNumber = errors.New("hex number has no digits after 0x") + ErrLeadingZero = errors.New("hex number has leading zero digits after 0x") + ErrOddLength = errors.New("hex string has odd length") + ErrUint64Range = errors.New("hex number does not fit into 64 bits") + ErrUintRange = fmt.Errorf("hex number does not fit into %d bits", uintBits) + ErrBig256Range = errors.New("hex number does not fit into 256 bits") +) + +// Decode decodes a hex string with 0x prefix. +func Decode(input string) ([]byte, error) { + if len(input) == 0 { + return nil, ErrEmptyString + } + if !has0xPrefix(input) { + return nil, ErrMissingPrefix + } + b, err := hex.DecodeString(input[2:]) + if err != nil { + err = mapError(err) + } + return b, err +} + +// MustDecode decodes a hex string with 0x prefix. It panics for invalid input. +func MustDecode(input string) []byte { + dec, err := Decode(input) + if err != nil { + panic(err) + } + return dec +} + +// Encode encodes b as a hex string with 0x prefix. +func Encode(b []byte) string { + enc := make([]byte, len(b)*2+2) + copy(enc, "0x") + hex.Encode(enc[2:], b) + return string(enc) +} + +// DecodeUint64 decodes a hex string with 0x prefix as a quantity. +func DecodeUint64(input string) (uint64, error) { + raw, err := checkNumber(input) + if err != nil { + return 0, err + } + dec, err := strconv.ParseUint(raw, 16, 64) + if err != nil { + err = mapError(err) + } + return dec, err +} + +// MustDecodeUint64 decodes a hex string with 0x prefix as a quantity. +// It panics for invalid input. +func MustDecodeUint64(input string) uint64 { + dec, err := DecodeUint64(input) + if err != nil { + panic(err) + } + return dec +} + +// EncodeUint64 encodes i as a hex string with 0x prefix. +func EncodeUint64(i uint64) string { + enc := make([]byte, 2, 10) + copy(enc, "0x") + return string(strconv.AppendUint(enc, i, 16)) +} + +var bigWordNibbles int + +func init() { + // This is a weird way to compute the number of nibbles required for big.Word. + // The usual way would be to use constant arithmetic but go vet can't handle that. + b, _ := new(big.Int).SetString("FFFFFFFFFF", 16) + switch len(b.Bits()) { + case 1: + bigWordNibbles = 16 + case 2: + bigWordNibbles = 8 + default: + panic("weird big.Word size") + } +} + +// DecodeBig decodes a hex string with 0x prefix as a quantity. +// Numbers larger than 256 bits are not accepted. +func DecodeBig(input string) (*big.Int, error) { + raw, err := checkNumber(input) + if err != nil { + return nil, err + } + if len(raw) > 64 { + return nil, ErrBig256Range + } + words := make([]big.Word, len(raw)/bigWordNibbles+1) + end := len(raw) + for i := range words { + start := end - bigWordNibbles + if start < 0 { + start = 0 + } + for ri := start; ri < end; ri++ { + nib := decodeNibble(raw[ri]) + if nib == badNibble { + return nil, ErrSyntax + } + words[i] *= 16 + words[i] += big.Word(nib) + } + end = start + } + dec := new(big.Int).SetBits(words) + return dec, nil +} + +// MustDecodeBig decodes a hex string with 0x prefix as a quantity. +// It panics for invalid input. +func MustDecodeBig(input string) *big.Int { + dec, err := DecodeBig(input) + if err != nil { + panic(err) + } + return dec +} + +// EncodeBig encodes bigint as a hex string with 0x prefix. +// The sign of the integer is ignored. +func EncodeBig(bigint *big.Int) string { + nbits := bigint.BitLen() + if nbits == 0 { + return "0x0" + } + return fmt.Sprintf("%#x", bigint) +} + +func has0xPrefix(input string) bool { + return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') +} + +func checkNumber(input string) (raw string, err error) { + if len(input) == 0 { + return "", ErrEmptyString + } + if !has0xPrefix(input) { + return "", ErrMissingPrefix + } + input = input[2:] + if len(input) == 0 { + return "", ErrEmptyNumber + } + if len(input) > 1 && input[0] == '0' { + return "", ErrLeadingZero + } + return input, nil +} + +const badNibble = ^uint64(0) + +func decodeNibble(in byte) uint64 { + switch { + case in >= '0' && in <= '9': + return uint64(in - '0') + case in >= 'A' && in <= 'F': + return uint64(in - 'A' + 10) + case in >= 'a' && in <= 'f': + return uint64(in - 'a' + 10) + default: + return badNibble + } +} + +func mapError(err error) error { + if err, ok := err.(*strconv.NumError); ok { + switch err.Err { + case strconv.ErrRange: + return ErrUint64Range + case strconv.ErrSyntax: + return ErrSyntax + } + } + if _, ok := err.(hex.InvalidByteError); ok { + return ErrSyntax + } + if err == hex.ErrLength { + return ErrOddLength + } + return err +} diff --git a/vendor/github.com/getamis/go-ethereum/common/hexutil/json.go b/vendor/github.com/getamis/go-ethereum/common/hexutil/json.go new file mode 100644 index 00000000..1bc1d014 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/hexutil/json.go @@ -0,0 +1,297 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package hexutil + +import ( + "encoding/hex" + "errors" + "fmt" + "math/big" + "strconv" +) + +var ( + textZero = []byte(`0x0`) + errNonString = errors.New("cannot unmarshal non-string as hex data") +) + +// Bytes marshals/unmarshals as a JSON string with 0x prefix. +// The empty slice marshals as "0x". +type Bytes []byte + +// MarshalText implements encoding.TextMarshaler +func (b Bytes) MarshalText() ([]byte, error) { + result := make([]byte, len(b)*2+2) + copy(result, `0x`) + hex.Encode(result[2:], b) + return result, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (b *Bytes) UnmarshalJSON(input []byte) error { + if !isString(input) { + return errNonString + } + return b.UnmarshalText(input[1 : len(input)-1]) +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (b *Bytes) UnmarshalText(input []byte) error { + raw, err := checkText(input, true) + if err != nil { + return err + } + dec := make([]byte, len(raw)/2) + if _, err = hex.Decode(dec, raw); err != nil { + err = mapError(err) + } else { + *b = dec + } + return err +} + +// String returns the hex encoding of b. +func (b Bytes) String() string { + return Encode(b) +} + +// UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out +// determines the required input length. This function is commonly used to implement the +// UnmarshalText method for fixed-size types. +func UnmarshalFixedText(typname string, input, out []byte) error { + raw, err := checkText(input, true) + if err != nil { + return err + } + if len(raw)/2 != len(out) { + return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) + } + // Pre-verify syntax before modifying out. + for _, b := range raw { + if decodeNibble(b) == badNibble { + return ErrSyntax + } + } + hex.Decode(out, raw) + return nil +} + +// UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The +// length of out determines the required input length. This function is commonly used to +// implement the UnmarshalText method for fixed-size types. +func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error { + raw, err := checkText(input, false) + if err != nil { + return err + } + if len(raw)/2 != len(out) { + return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) + } + // Pre-verify syntax before modifying out. + for _, b := range raw { + if decodeNibble(b) == badNibble { + return ErrSyntax + } + } + hex.Decode(out, raw) + return nil +} + +// Big marshals/unmarshals as a JSON string with 0x prefix. +// The zero value marshals as "0x0". +// +// Negative integers are not supported at this time. Attempting to marshal them will +// return an error. Values larger than 256bits are rejected by Unmarshal but will be +// marshaled without error. +type Big big.Int + +// MarshalText implements encoding.TextMarshaler +func (b Big) MarshalText() ([]byte, error) { + return []byte(EncodeBig((*big.Int)(&b))), nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (b *Big) UnmarshalJSON(input []byte) error { + if !isString(input) { + return errNonString + } + return b.UnmarshalText(input[1 : len(input)-1]) +} + +// UnmarshalText implements encoding.TextUnmarshaler +func (b *Big) UnmarshalText(input []byte) error { + raw, err := checkNumberText(input) + if err != nil { + return err + } + if len(raw) > 64 { + return ErrBig256Range + } + words := make([]big.Word, len(raw)/bigWordNibbles+1) + end := len(raw) + for i := range words { + start := end - bigWordNibbles + if start < 0 { + start = 0 + } + for ri := start; ri < end; ri++ { + nib := decodeNibble(raw[ri]) + if nib == badNibble { + return ErrSyntax + } + words[i] *= 16 + words[i] += big.Word(nib) + } + end = start + } + var dec big.Int + dec.SetBits(words) + *b = (Big)(dec) + return nil +} + +// ToInt converts b to a big.Int. +func (b *Big) ToInt() *big.Int { + return (*big.Int)(b) +} + +// String returns the hex encoding of b. +func (b *Big) String() string { + return EncodeBig(b.ToInt()) +} + +// Uint64 marshals/unmarshals as a JSON string with 0x prefix. +// The zero value marshals as "0x0". +type Uint64 uint64 + +// MarshalText implements encoding.TextMarshaler. +func (b Uint64) MarshalText() ([]byte, error) { + buf := make([]byte, 2, 10) + copy(buf, `0x`) + buf = strconv.AppendUint(buf, uint64(b), 16) + return buf, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (b *Uint64) UnmarshalJSON(input []byte) error { + if !isString(input) { + return errNonString + } + return b.UnmarshalText(input[1 : len(input)-1]) +} + +// UnmarshalText implements encoding.TextUnmarshaler +func (b *Uint64) UnmarshalText(input []byte) error { + raw, err := checkNumberText(input) + if err != nil { + return err + } + if len(raw) > 16 { + return ErrUint64Range + } + var dec uint64 + for _, byte := range raw { + nib := decodeNibble(byte) + if nib == badNibble { + return ErrSyntax + } + dec *= 16 + dec += uint64(nib) + } + *b = Uint64(dec) + return nil +} + +// String returns the hex encoding of b. +func (b Uint64) String() string { + return EncodeUint64(uint64(b)) +} + +// Uint marshals/unmarshals as a JSON string with 0x prefix. +// The zero value marshals as "0x0". +type Uint uint + +// MarshalText implements encoding.TextMarshaler. +func (b Uint) MarshalText() ([]byte, error) { + return Uint64(b).MarshalText() +} + +// UnmarshalJSON implements json.Unmarshaler. +func (b *Uint) UnmarshalJSON(input []byte) error { + if !isString(input) { + return errNonString + } + return b.UnmarshalText(input[1 : len(input)-1]) +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (b *Uint) UnmarshalText(input []byte) error { + var u64 Uint64 + err := u64.UnmarshalText(input) + if u64 > Uint64(^uint(0)) || err == ErrUint64Range { + return ErrUintRange + } else if err != nil { + return err + } + *b = Uint(u64) + return nil +} + +// String returns the hex encoding of b. +func (b Uint) String() string { + return EncodeUint64(uint64(b)) +} + +func isString(input []byte) bool { + return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' +} + +func bytesHave0xPrefix(input []byte) bool { + return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') +} + +func checkText(input []byte, wantPrefix bool) ([]byte, error) { + if len(input) == 0 { + return nil, nil // empty strings are allowed + } + if bytesHave0xPrefix(input) { + input = input[2:] + } else if wantPrefix { + return nil, ErrMissingPrefix + } + if len(input)%2 != 0 { + return nil, ErrOddLength + } + return input, nil +} + +func checkNumberText(input []byte) (raw []byte, err error) { + if len(input) == 0 { + return nil, nil // empty strings are allowed + } + if !bytesHave0xPrefix(input) { + return nil, ErrMissingPrefix + } + input = input[2:] + if len(input) == 0 { + return nil, ErrEmptyNumber + } + if len(input) > 1 && input[0] == '0' { + return nil, ErrLeadingZero + } + return input, nil +} diff --git a/vendor/github.com/getamis/go-ethereum/common/path.go b/vendor/github.com/getamis/go-ethereum/common/path.go new file mode 100644 index 00000000..bd8da86e --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/path.go @@ -0,0 +1,47 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "fmt" + "os" + "path/filepath" + "runtime" +) + +// MakeName creates a node name that follows the ethereum convention +// for such names. It adds the operation system name and Go runtime version +// the name. +func MakeName(name, version string) string { + return fmt.Sprintf("%s/v%s/%s/%s", name, version, runtime.GOOS, runtime.Version()) +} + +func FileExist(filePath string) bool { + _, err := os.Stat(filePath) + if err != nil && os.IsNotExist(err) { + return false + } + + return true +} + +func AbsolutePath(Datadir string, filename string) string { + if filepath.IsAbs(filename) { + return filename + } + return filepath.Join(Datadir, filename) +} diff --git a/vendor/github.com/getamis/go-ethereum/common/size.go b/vendor/github.com/getamis/go-ethereum/common/size.go new file mode 100644 index 00000000..c5a0cb0f --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/size.go @@ -0,0 +1,37 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "fmt" +) + +type StorageSize float64 + +func (self StorageSize) String() string { + if self > 1000000 { + return fmt.Sprintf("%.2f mB", self/1000000) + } else if self > 1000 { + return fmt.Sprintf("%.2f kB", self/1000) + } else { + return fmt.Sprintf("%.2f B", self) + } +} + +func (self StorageSize) Int64() int64 { + return int64(self) +} diff --git a/vendor/github.com/getamis/go-ethereum/common/test_utils.go b/vendor/github.com/getamis/go-ethereum/common/test_utils.go new file mode 100644 index 00000000..a848642f --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/test_utils.go @@ -0,0 +1,53 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "encoding/json" + "fmt" + "io/ioutil" +) + +// LoadJSON reads the given file and unmarshals its content. +func LoadJSON(file string, val interface{}) error { + content, err := ioutil.ReadFile(file) + if err != nil { + return err + } + if err := json.Unmarshal(content, val); err != nil { + if syntaxerr, ok := err.(*json.SyntaxError); ok { + line := findLine(content, syntaxerr.Offset) + return fmt.Errorf("JSON syntax error at %v:%v: %v", file, line, err) + } + return fmt.Errorf("JSON unmarshal error in %v: %v", file, err) + } + return nil +} + +// findLine returns the line number for the given offset into data. +func findLine(data []byte, offset int64) (line int) { + line = 1 + for i, r := range string(data) { + if int64(i) >= offset { + return + } + if r == '\n' { + line++ + } + } + return +} diff --git a/vendor/github.com/getamis/go-ethereum/common/types.go b/vendor/github.com/getamis/go-ethereum/common/types.go new file mode 100644 index 00000000..05288bf4 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/types.go @@ -0,0 +1,208 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package common + +import ( + "encoding/hex" + "fmt" + "math/big" + "math/rand" + "reflect" + + "github.com/ethereum/go-ethereum/common/hexutil" +) + +const ( + HashLength = 32 + AddressLength = 20 +) + +// Hash represents the 32 byte Keccak256 hash of arbitrary data. +type Hash [HashLength]byte + +func BytesToHash(b []byte) Hash { + var h Hash + h.SetBytes(b) + return h +} +func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } +func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } +func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } + +// Get the string representation of the underlying hash +func (h Hash) Str() string { return string(h[:]) } +func (h Hash) Bytes() []byte { return h[:] } +func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } +func (h Hash) Hex() string { return hexutil.Encode(h[:]) } + +// TerminalString implements log.TerminalStringer, formatting a string for console +// output during logging. +func (h Hash) TerminalString() string { + return fmt.Sprintf("%x…%x", h[:3], h[29:]) +} + +// String implements the stringer interface and is used also by the logger when +// doing full logging into a file. +func (h Hash) String() string { + return h.Hex() +} + +// Format implements fmt.Formatter, forcing the byte slice to be formatted as is, +// without going through the stringer interface used for logging. +func (h Hash) Format(s fmt.State, c rune) { + fmt.Fprintf(s, "%"+string(c), h[:]) +} + +// UnmarshalText parses a hash in hex syntax. +func (h *Hash) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedText("Hash", input, h[:]) +} + +// MarshalText returns the hex representation of h. +func (h Hash) MarshalText() ([]byte, error) { + return hexutil.Bytes(h[:]).MarshalText() +} + +// Sets the hash to the value of b. If b is larger than len(h) it will panic +func (h *Hash) SetBytes(b []byte) { + if len(b) > len(h) { + b = b[len(b)-HashLength:] + } + + copy(h[HashLength-len(b):], b) +} + +// Set string `s` to h. If s is larger than len(h) it will panic +func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) } + +// Sets h to other +func (h *Hash) Set(other Hash) { + for i, v := range other { + h[i] = v + } +} + +// Generate implements testing/quick.Generator. +func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { + m := rand.Intn(len(h)) + for i := len(h) - 1; i > m; i-- { + h[i] = byte(rand.Uint32()) + } + return reflect.ValueOf(h) +} + +func EmptyHash(h Hash) bool { + return h == Hash{} +} + +// UnprefixedHash allows marshaling a Hash without 0x prefix. +type UnprefixedHash Hash + +// UnmarshalText decodes the hash from hex. The 0x prefix is optional. +func (h *UnprefixedHash) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:]) +} + +// MarshalText encodes the hash as hex. +func (h UnprefixedHash) MarshalText() ([]byte, error) { + return []byte(hex.EncodeToString(h[:])), nil +} + +/////////// Address + +// Address represents the 20 byte address of an Ethereum account. +type Address [AddressLength]byte + +func BytesToAddress(b []byte) Address { + var a Address + a.SetBytes(b) + return a +} +func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) } +func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } +func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } + +// IsHexAddress verifies whether a string can represent a valid hex-encoded +// Ethereum address or not. +func IsHexAddress(s string) bool { + if len(s) == 2+2*AddressLength && IsHex(s) { + return true + } + if len(s) == 2*AddressLength && IsHex("0x"+s) { + return true + } + return false +} + +// Get the string representation of the underlying address +func (a Address) Str() string { return string(a[:]) } +func (a Address) Bytes() []byte { return a[:] } +func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } +func (a Address) Hash() Hash { return BytesToHash(a[:]) } +func (a Address) Hex() string { return hexutil.Encode(a[:]) } + +// String implements the stringer interface and is used also by the logger. +func (a Address) String() string { + return a.Hex() +} + +// Format implements fmt.Formatter, forcing the byte slice to be formatted as is, +// without going through the stringer interface used for logging. +func (a Address) Format(s fmt.State, c rune) { + fmt.Fprintf(s, "%"+string(c), a[:]) +} + +// Sets the address to the value of b. If b is larger than len(a) it will panic +func (a *Address) SetBytes(b []byte) { + if len(b) > len(a) { + b = b[len(b)-AddressLength:] + } + copy(a[AddressLength-len(b):], b) +} + +// Set string `s` to a. If s is larger than len(a) it will panic +func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) } + +// Sets a to other +func (a *Address) Set(other Address) { + for i, v := range other { + a[i] = v + } +} + +// MarshalText returns the hex representation of a. +func (a Address) MarshalText() ([]byte, error) { + return hexutil.Bytes(a[:]).MarshalText() +} + +// UnmarshalText parses a hash in hex syntax. +func (a *Address) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedText("Address", input, a[:]) +} + +// UnprefixedHash allows marshaling an Address without 0x prefix. +type UnprefixedAddress Address + +// UnmarshalText decodes the address from hex. The 0x prefix is optional. +func (a *UnprefixedAddress) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:]) +} + +// MarshalText encodes the address as hex. +func (a UnprefixedAddress) MarshalText() ([]byte, error) { + return []byte(hex.EncodeToString(a[:])), nil +} diff --git a/vendor/github.com/getamis/go-ethereum/common/types_template.go b/vendor/github.com/getamis/go-ethereum/common/types_template.go new file mode 100644 index 00000000..9a8f2997 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/common/types_template.go @@ -0,0 +1,64 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build none +//sed -e 's/_N_/Hash/g' -e 's/_S_/32/g' -e '1d' types_template.go | gofmt -w hash.go + +package common + +import "math/big" + +type _N_ [_S_]byte + +func BytesTo_N_(b []byte) _N_ { + var h _N_ + h.SetBytes(b) + return h +} +func StringTo_N_(s string) _N_ { return BytesTo_N_([]byte(s)) } +func BigTo_N_(b *big.Int) _N_ { return BytesTo_N_(b.Bytes()) } +func HexTo_N_(s string) _N_ { return BytesTo_N_(FromHex(s)) } + +// Don't use the default 'String' method in case we want to overwrite + +// Get the string representation of the underlying hash +func (h _N_) Str() string { return string(h[:]) } +func (h _N_) Bytes() []byte { return h[:] } +func (h _N_) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } +func (h _N_) Hex() string { return "0x" + Bytes2Hex(h[:]) } + +// Sets the hash to the value of b. If b is larger than len(h) it will panic +func (h *_N_) SetBytes(b []byte) { + // Use the right most bytes + if len(b) > len(h) { + b = b[len(b)-_S_:] + } + + // Reverse the loop + for i := len(b) - 1; i >= 0; i-- { + h[_S_-len(b)+i] = b[i] + } +} + +// Set string `s` to h. If s is larger than len(h) it will panic +func (h *_N_) SetString(s string) { h.SetBytes([]byte(s)) } + +// Sets h to other +func (h *_N_) Set(other _N_) { + for i, v := range other { + h[i] = v + } +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/block.go b/vendor/github.com/getamis/go-ethereum/core/types/block.go new file mode 100644 index 00000000..4f304994 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/block.go @@ -0,0 +1,455 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package types contains data types related to Ethereum consensus. +package types + +import ( + "encoding/binary" + "fmt" + "io" + "math/big" + "sort" + "sync/atomic" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto/sha3" + "github.com/ethereum/go-ethereum/rlp" +) + +var ( + EmptyRootHash = DeriveSha(Transactions{}) + EmptyUncleHash = CalcUncleHash(nil) +) + +// A BlockNonce is a 64-bit hash which proves (combined with the +// mix-hash) that a sufficient amount of computation has been carried +// out on a block. +type BlockNonce [8]byte + +// EncodeNonce converts the given integer to a block nonce. +func EncodeNonce(i uint64) BlockNonce { + var n BlockNonce + binary.BigEndian.PutUint64(n[:], i) + return n +} + +// Uint64 returns the integer value of a block nonce. +func (n BlockNonce) Uint64() uint64 { + return binary.BigEndian.Uint64(n[:]) +} + +// MarshalText encodes n as a hex string with 0x prefix. +func (n BlockNonce) MarshalText() ([]byte, error) { + return hexutil.Bytes(n[:]).MarshalText() +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (n *BlockNonce) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedText("BlockNonce", input, n[:]) +} + +//go:generate gencodec -type Header -field-override headerMarshaling -out gen_header_json.go + +// Header represents a block header in the Ethereum blockchain. +type Header struct { + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase common.Address `json:"miner" gencodec:"required"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *big.Int `json:"difficulty" gencodec:"required"` + Number *big.Int `json:"number" gencodec:"required"` + GasLimit *big.Int `json:"gasLimit" gencodec:"required"` + GasUsed *big.Int `json:"gasUsed" gencodec:"required"` + Time *big.Int `json:"timestamp" gencodec:"required"` + Extra []byte `json:"extraData" gencodec:"required"` + MixDigest common.Hash `json:"mixHash" gencodec:"required"` + Nonce BlockNonce `json:"nonce" gencodec:"required"` +} + +// field type overrides for gencodec +type headerMarshaling struct { + Difficulty *hexutil.Big + Number *hexutil.Big + GasLimit *hexutil.Big + GasUsed *hexutil.Big + Time *hexutil.Big + Extra hexutil.Bytes + Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON +} + +// Hash returns the block hash of the header, which is simply the keccak256 hash of its +// RLP encoding. It returns block hash of istanbul if the mix digest of header is conforms to +// specific istanbul digest. +func (h *Header) Hash() common.Hash { + if h.MixDigest == IstanbulDigest { + // Seal is reserved in extra-data. To prove block is signed by the proposer. + if istanbulHeader := IstanbulFilteredHeader(h, true); istanbulHeader != nil { + return rlpHash(istanbulHeader) + } else { + return rlpHash(h) + } + } + return rlpHash(h) +} + +// HashNoNonce returns the hash which is used as input for the proof-of-work search. +func (h *Header) HashNoNonce() common.Hash { + return rlpHash([]interface{}{ + h.ParentHash, + h.UncleHash, + h.Coinbase, + h.Root, + h.TxHash, + h.ReceiptHash, + h.Bloom, + h.Difficulty, + h.Number, + h.GasLimit, + h.GasUsed, + h.Time, + h.Extra, + }) +} + +func rlpHash(x interface{}) (h common.Hash) { + hw := sha3.NewKeccak256() + rlp.Encode(hw, x) + hw.Sum(h[:0]) + return h +} + +// Body is a simple (mutable, non-safe) data container for storing and moving +// a block's data contents (transactions and uncles) together. +type Body struct { + Transactions []*Transaction + Uncles []*Header +} + +// Block represents an entire block in the Ethereum blockchain. +type Block struct { + header *Header + uncles []*Header + transactions Transactions + + // caches + hash atomic.Value + size atomic.Value + + // Td is used by package core to store the total difficulty + // of the chain up to and including the block. + td *big.Int + + // These fields are used by package eth to track + // inter-peer block relay. + ReceivedAt time.Time + ReceivedFrom interface{} +} + +// DeprecatedTd is an old relic for extracting the TD of a block. It is in the +// code solely to facilitate upgrading the database from the old format to the +// new, after which it should be deleted. Do not use! +func (b *Block) DeprecatedTd() *big.Int { + return b.td +} + +// [deprecated by eth/63] +// StorageBlock defines the RLP encoding of a Block stored in the +// state database. The StorageBlock encoding contains fields that +// would otherwise need to be recomputed. +type StorageBlock Block + +// "external" block encoding. used for eth protocol, etc. +type extblock struct { + Header *Header + Txs []*Transaction + Uncles []*Header +} + +// [deprecated by eth/63] +// "storage" block encoding. used for database. +type storageblock struct { + Header *Header + Txs []*Transaction + Uncles []*Header + TD *big.Int +} + +// NewBlock creates a new block. The input data is copied, +// changes to header and to the field values will not affect the +// block. +// +// The values of TxHash, UncleHash, ReceiptHash and Bloom in header +// are ignored and set to values derived from the given txs, uncles +// and receipts. +func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt) *Block { + b := &Block{header: CopyHeader(header), td: new(big.Int)} + + // TODO: panic if len(txs) != len(receipts) + if len(txs) == 0 { + b.header.TxHash = EmptyRootHash + } else { + b.header.TxHash = DeriveSha(Transactions(txs)) + b.transactions = make(Transactions, len(txs)) + copy(b.transactions, txs) + } + + if len(receipts) == 0 { + b.header.ReceiptHash = EmptyRootHash + } else { + b.header.ReceiptHash = DeriveSha(Receipts(receipts)) + b.header.Bloom = CreateBloom(receipts) + } + + if len(uncles) == 0 { + b.header.UncleHash = EmptyUncleHash + } else { + b.header.UncleHash = CalcUncleHash(uncles) + b.uncles = make([]*Header, len(uncles)) + for i := range uncles { + b.uncles[i] = CopyHeader(uncles[i]) + } + } + + return b +} + +// NewBlockWithHeader creates a block with the given header data. The +// header data is copied, changes to header and to the field values +// will not affect the block. +func NewBlockWithHeader(header *Header) *Block { + return &Block{header: CopyHeader(header)} +} + +// CopyHeader creates a deep copy of a block header to prevent side effects from +// modifying a header variable. +func CopyHeader(h *Header) *Header { + cpy := *h + if cpy.Time = new(big.Int); h.Time != nil { + cpy.Time.Set(h.Time) + } + if cpy.Difficulty = new(big.Int); h.Difficulty != nil { + cpy.Difficulty.Set(h.Difficulty) + } + if cpy.Number = new(big.Int); h.Number != nil { + cpy.Number.Set(h.Number) + } + if cpy.GasLimit = new(big.Int); h.GasLimit != nil { + cpy.GasLimit.Set(h.GasLimit) + } + if cpy.GasUsed = new(big.Int); h.GasUsed != nil { + cpy.GasUsed.Set(h.GasUsed) + } + if len(h.Extra) > 0 { + cpy.Extra = make([]byte, len(h.Extra)) + copy(cpy.Extra, h.Extra) + } + return &cpy +} + +// DecodeRLP decodes the Ethereum +func (b *Block) DecodeRLP(s *rlp.Stream) error { + var eb extblock + _, size, _ := s.Kind() + if err := s.Decode(&eb); err != nil { + return err + } + b.header, b.uncles, b.transactions = eb.Header, eb.Uncles, eb.Txs + b.size.Store(common.StorageSize(rlp.ListSize(size))) + return nil +} + +// EncodeRLP serializes b into the Ethereum RLP block format. +func (b *Block) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, extblock{ + Header: b.header, + Txs: b.transactions, + Uncles: b.uncles, + }) +} + +// [deprecated by eth/63] +func (b *StorageBlock) DecodeRLP(s *rlp.Stream) error { + var sb storageblock + if err := s.Decode(&sb); err != nil { + return err + } + b.header, b.uncles, b.transactions, b.td = sb.Header, sb.Uncles, sb.Txs, sb.TD + return nil +} + +// TODO: copies + +func (b *Block) Uncles() []*Header { return b.uncles } +func (b *Block) Transactions() Transactions { return b.transactions } + +func (b *Block) Transaction(hash common.Hash) *Transaction { + for _, transaction := range b.transactions { + if transaction.Hash() == hash { + return transaction + } + } + return nil +} + +func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) } +func (b *Block) GasLimit() *big.Int { return new(big.Int).Set(b.header.GasLimit) } +func (b *Block) GasUsed() *big.Int { return new(big.Int).Set(b.header.GasUsed) } +func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) } +func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) } + +func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() } +func (b *Block) MixDigest() common.Hash { return b.header.MixDigest } +func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) } +func (b *Block) Bloom() Bloom { return b.header.Bloom } +func (b *Block) Coinbase() common.Address { return b.header.Coinbase } +func (b *Block) Root() common.Hash { return b.header.Root } +func (b *Block) ParentHash() common.Hash { return b.header.ParentHash } +func (b *Block) TxHash() common.Hash { return b.header.TxHash } +func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash } +func (b *Block) UncleHash() common.Hash { return b.header.UncleHash } +func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) } + +func (b *Block) Header() *Header { return CopyHeader(b.header) } + +// Body returns the non-header content of the block. +func (b *Block) Body() *Body { return &Body{b.transactions, b.uncles} } + +func (b *Block) HashNoNonce() common.Hash { + return b.header.HashNoNonce() +} + +func (b *Block) Size() common.StorageSize { + if size := b.size.Load(); size != nil { + return size.(common.StorageSize) + } + c := writeCounter(0) + rlp.Encode(&c, b) + b.size.Store(common.StorageSize(c)) + return common.StorageSize(c) +} + +type writeCounter common.StorageSize + +func (c *writeCounter) Write(b []byte) (int, error) { + *c += writeCounter(len(b)) + return len(b), nil +} + +func CalcUncleHash(uncles []*Header) common.Hash { + return rlpHash(uncles) +} + +// WithSeal returns a new block with the data from b but the header replaced with +// the sealed one. +func (b *Block) WithSeal(header *Header) *Block { + cpy := *header + + return &Block{ + header: &cpy, + transactions: b.transactions, + uncles: b.uncles, + } +} + +// WithBody returns a new block with the given transaction and uncle contents. +func (b *Block) WithBody(transactions []*Transaction, uncles []*Header) *Block { + block := &Block{ + header: CopyHeader(b.header), + transactions: make([]*Transaction, len(transactions)), + uncles: make([]*Header, len(uncles)), + } + copy(block.transactions, transactions) + for i := range uncles { + block.uncles[i] = CopyHeader(uncles[i]) + } + return block +} + +// Hash returns the keccak256 hash of b's header. +// The hash is computed on the first call and cached thereafter. +func (b *Block) Hash() common.Hash { + if hash := b.hash.Load(); hash != nil { + return hash.(common.Hash) + } + v := b.header.Hash() + b.hash.Store(v) + return v +} + +func (b *Block) String() string { + str := fmt.Sprintf(`Block(#%v): Size: %v { +MinerHash: %x +%v +Transactions: +%v +Uncles: +%v +} +`, b.Number(), b.Size(), b.header.HashNoNonce(), b.header, b.transactions, b.uncles) + return str +} + +func (h *Header) String() string { + return fmt.Sprintf(`Header(%x): +[ + ParentHash: %x + UncleHash: %x + Coinbase: %x + Root: %x + TxSha %x + ReceiptSha: %x + Bloom: %x + Difficulty: %v + Number: %v + GasLimit: %v + GasUsed: %v + Time: %v + Extra: %s + MixDigest: %x + Nonce: %x +]`, h.Hash(), h.ParentHash, h.UncleHash, h.Coinbase, h.Root, h.TxHash, h.ReceiptHash, h.Bloom, h.Difficulty, h.Number, h.GasLimit, h.GasUsed, h.Time, h.Extra, h.MixDigest, h.Nonce) +} + +type Blocks []*Block + +type BlockBy func(b1, b2 *Block) bool + +func (self BlockBy) Sort(blocks Blocks) { + bs := blockSorter{ + blocks: blocks, + by: self, + } + sort.Sort(bs) +} + +type blockSorter struct { + blocks Blocks + by func(b1, b2 *Block) bool +} + +func (self blockSorter) Len() int { return len(self.blocks) } +func (self blockSorter) Swap(i, j int) { + self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i] +} +func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) } + +func Number(b1, b2 *Block) bool { return b1.header.Number.Cmp(b2.header.Number) < 0 } diff --git a/vendor/github.com/getamis/go-ethereum/core/types/bloom9.go b/vendor/github.com/getamis/go-ethereum/core/types/bloom9.go new file mode 100644 index 00000000..60aacc30 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/bloom9.go @@ -0,0 +1,130 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" +) + +type bytesBacked interface { + Bytes() []byte +} + +const bloomLength = 256 + +// Bloom represents a 256 bit bloom filter. +type Bloom [bloomLength]byte + +// BytesToBloom converts a byte slice to a bloom filter. +// It panics if b is not of suitable size. +func BytesToBloom(b []byte) Bloom { + var bloom Bloom + bloom.SetBytes(b) + return bloom +} + +// SetBytes sets the content of b to the given bytes. +// It panics if d is not of suitable size. +func (b *Bloom) SetBytes(d []byte) { + if len(b) < len(d) { + panic(fmt.Sprintf("bloom bytes too big %d %d", len(b), len(d))) + } + copy(b[bloomLength-len(d):], d) +} + +// Add adds d to the filter. Future calls of Test(d) will return true. +func (b *Bloom) Add(d *big.Int) { + bin := new(big.Int).SetBytes(b[:]) + bin.Or(bin, bloom9(d.Bytes())) + b.SetBytes(bin.Bytes()) +} + +// Big converts b to a big integer. +func (b Bloom) Big() *big.Int { + return new(big.Int).SetBytes(b[:]) +} + +func (b Bloom) Bytes() []byte { + return b[:] +} + +func (b Bloom) Test(test *big.Int) bool { + return BloomLookup(b, test) +} + +func (b Bloom) TestBytes(test []byte) bool { + return b.Test(new(big.Int).SetBytes(test)) + +} + +// MarshalText encodes b as a hex string with 0x prefix. +func (b Bloom) MarshalText() ([]byte, error) { + return hexutil.Bytes(b[:]).MarshalText() +} + +// UnmarshalText b as a hex string with 0x prefix. +func (b *Bloom) UnmarshalText(input []byte) error { + return hexutil.UnmarshalFixedText("Bloom", input, b[:]) +} + +func CreateBloom(receipts Receipts) Bloom { + bin := new(big.Int) + for _, receipt := range receipts { + bin.Or(bin, LogsBloom(receipt.Logs)) + } + + return BytesToBloom(bin.Bytes()) +} + +func LogsBloom(logs []*Log) *big.Int { + bin := new(big.Int) + for _, log := range logs { + bin.Or(bin, bloom9(log.Address.Bytes())) + for _, b := range log.Topics { + bin.Or(bin, bloom9(b[:])) + } + } + + return bin +} + +func bloom9(b []byte) *big.Int { + b = crypto.Keccak256(b[:]) + + r := new(big.Int) + + for i := 0; i < 6; i += 2 { + t := big.NewInt(1) + b := (uint(b[i+1]) + (uint(b[i]) << 8)) & 2047 + r.Or(r, t.Lsh(t, b)) + } + + return r +} + +var Bloom9 = bloom9 + +func BloomLookup(bin Bloom, topic bytesBacked) bool { + bloom := bin.Big() + cmp := bloom9(topic.Bytes()[:]) + + return bloom.And(bloom, cmp).Cmp(cmp) == 0 +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/derive_sha.go b/vendor/github.com/getamis/go-ethereum/core/types/derive_sha.go new file mode 100644 index 00000000..00c42c5b --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/derive_sha.go @@ -0,0 +1,41 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "bytes" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" +) + +type DerivableList interface { + Len() int + GetRlp(i int) []byte +} + +func DeriveSha(list DerivableList) common.Hash { + keybuf := new(bytes.Buffer) + trie := new(trie.Trie) + for i := 0; i < list.Len(); i++ { + keybuf.Reset() + rlp.Encode(keybuf, uint(i)) + trie.Update(keybuf.Bytes(), list.GetRlp(i)) + } + return trie.Hash() +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/gen_header_json.go b/vendor/github.com/getamis/go-ethereum/core/types/gen_header_json.go new file mode 100644 index 00000000..bcff7a94 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/gen_header_json.go @@ -0,0 +1,136 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package types + +import ( + "encoding/json" + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +func (h Header) MarshalJSON() ([]byte, error) { + type Header struct { + ParentHash common.Hash `json:"parentHash" gencodec:"required"` + UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase common.Address `json:"miner" gencodec:"required"` + Root common.Hash `json:"stateRoot" gencodec:"required"` + TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + Number *hexutil.Big `json:"number" gencodec:"required"` + GasLimit *hexutil.Big `json:"gasLimit" gencodec:"required"` + GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"` + Time *hexutil.Big `json:"timestamp" gencodec:"required"` + Extra hexutil.Bytes `json:"extraData" gencodec:"required"` + MixDigest common.Hash `json:"mixHash" gencodec:"required"` + Nonce BlockNonce `json:"nonce" gencodec:"required"` + Hash common.Hash `json:"hash"` + } + var enc Header + enc.ParentHash = h.ParentHash + enc.UncleHash = h.UncleHash + enc.Coinbase = h.Coinbase + enc.Root = h.Root + enc.TxHash = h.TxHash + enc.ReceiptHash = h.ReceiptHash + enc.Bloom = h.Bloom + enc.Difficulty = (*hexutil.Big)(h.Difficulty) + enc.Number = (*hexutil.Big)(h.Number) + enc.GasLimit = (*hexutil.Big)(h.GasLimit) + enc.GasUsed = (*hexutil.Big)(h.GasUsed) + enc.Time = (*hexutil.Big)(h.Time) + enc.Extra = h.Extra + enc.MixDigest = h.MixDigest + enc.Nonce = h.Nonce + enc.Hash = h.Hash() + return json.Marshal(&enc) +} + +func (h *Header) UnmarshalJSON(input []byte) error { + type Header struct { + ParentHash *common.Hash `json:"parentHash" gencodec:"required"` + UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"` + Coinbase *common.Address `json:"miner" gencodec:"required"` + Root *common.Hash `json:"stateRoot" gencodec:"required"` + TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"` + ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"` + Bloom *Bloom `json:"logsBloom" gencodec:"required"` + Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"` + Number *hexutil.Big `json:"number" gencodec:"required"` + GasLimit *hexutil.Big `json:"gasLimit" gencodec:"required"` + GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"` + Time *hexutil.Big `json:"timestamp" gencodec:"required"` + Extra hexutil.Bytes `json:"extraData" gencodec:"required"` + MixDigest *common.Hash `json:"mixHash" gencodec:"required"` + Nonce *BlockNonce `json:"nonce" gencodec:"required"` + } + var dec Header + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.ParentHash == nil { + return errors.New("missing required field 'parentHash' for Header") + } + h.ParentHash = *dec.ParentHash + if dec.UncleHash == nil { + return errors.New("missing required field 'sha3Uncles' for Header") + } + h.UncleHash = *dec.UncleHash + if dec.Coinbase == nil { + return errors.New("missing required field 'miner' for Header") + } + h.Coinbase = *dec.Coinbase + if dec.Root == nil { + return errors.New("missing required field 'stateRoot' for Header") + } + h.Root = *dec.Root + if dec.TxHash == nil { + return errors.New("missing required field 'transactionsRoot' for Header") + } + h.TxHash = *dec.TxHash + if dec.ReceiptHash == nil { + return errors.New("missing required field 'receiptsRoot' for Header") + } + h.ReceiptHash = *dec.ReceiptHash + if dec.Bloom == nil { + return errors.New("missing required field 'logsBloom' for Header") + } + h.Bloom = *dec.Bloom + if dec.Difficulty == nil { + return errors.New("missing required field 'difficulty' for Header") + } + h.Difficulty = (*big.Int)(dec.Difficulty) + if dec.Number == nil { + return errors.New("missing required field 'number' for Header") + } + h.Number = (*big.Int)(dec.Number) + if dec.GasLimit == nil { + return errors.New("missing required field 'gasLimit' for Header") + } + h.GasLimit = (*big.Int)(dec.GasLimit) + if dec.GasUsed == nil { + return errors.New("missing required field 'gasUsed' for Header") + } + h.GasUsed = (*big.Int)(dec.GasUsed) + if dec.Time == nil { + return errors.New("missing required field 'timestamp' for Header") + } + h.Time = (*big.Int)(dec.Time) + if dec.Extra == nil { + return errors.New("missing required field 'extraData' for Header") + } + h.Extra = dec.Extra + if dec.MixDigest == nil { + return errors.New("missing required field 'mixHash' for Header") + } + h.MixDigest = *dec.MixDigest + if dec.Nonce == nil { + return errors.New("missing required field 'nonce' for Header") + } + h.Nonce = *dec.Nonce + return nil +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/gen_log_json.go b/vendor/github.com/getamis/go-ethereum/core/types/gen_log_json.go new file mode 100644 index 00000000..92c699c2 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/gen_log_json.go @@ -0,0 +1,88 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package types + +import ( + "encoding/json" + "errors" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +func (l Log) MarshalJSON() ([]byte, error) { + type Log struct { + Address common.Address `json:"address" gencodec:"required"` + Topics []common.Hash `json:"topics" gencodec:"required"` + Data hexutil.Bytes `json:"data" gencodec:"required"` + BlockNumber hexutil.Uint64 `json:"blockNumber"` + TxHash common.Hash `json:"transactionHash" gencodec:"required"` + TxIndex hexutil.Uint `json:"transactionIndex" gencodec:"required"` + BlockHash common.Hash `json:"blockHash"` + Index hexutil.Uint `json:"logIndex" gencodec:"required"` + Removed bool `json:"removed"` + } + var enc Log + enc.Address = l.Address + enc.Topics = l.Topics + enc.Data = l.Data + enc.BlockNumber = hexutil.Uint64(l.BlockNumber) + enc.TxHash = l.TxHash + enc.TxIndex = hexutil.Uint(l.TxIndex) + enc.BlockHash = l.BlockHash + enc.Index = hexutil.Uint(l.Index) + enc.Removed = l.Removed + return json.Marshal(&enc) +} + +func (l *Log) UnmarshalJSON(input []byte) error { + type Log struct { + Address *common.Address `json:"address" gencodec:"required"` + Topics []common.Hash `json:"topics" gencodec:"required"` + Data hexutil.Bytes `json:"data" gencodec:"required"` + BlockNumber *hexutil.Uint64 `json:"blockNumber"` + TxHash *common.Hash `json:"transactionHash" gencodec:"required"` + TxIndex *hexutil.Uint `json:"transactionIndex" gencodec:"required"` + BlockHash *common.Hash `json:"blockHash"` + Index *hexutil.Uint `json:"logIndex" gencodec:"required"` + Removed *bool `json:"removed"` + } + var dec Log + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.Address == nil { + return errors.New("missing required field 'address' for Log") + } + l.Address = *dec.Address + if dec.Topics == nil { + return errors.New("missing required field 'topics' for Log") + } + l.Topics = dec.Topics + if dec.Data == nil { + return errors.New("missing required field 'data' for Log") + } + l.Data = dec.Data + if dec.BlockNumber != nil { + l.BlockNumber = uint64(*dec.BlockNumber) + } + if dec.TxHash == nil { + return errors.New("missing required field 'transactionHash' for Log") + } + l.TxHash = *dec.TxHash + if dec.TxIndex == nil { + return errors.New("missing required field 'transactionIndex' for Log") + } + l.TxIndex = uint(*dec.TxIndex) + if dec.BlockHash != nil { + l.BlockHash = *dec.BlockHash + } + if dec.Index == nil { + return errors.New("missing required field 'logIndex' for Log") + } + l.Index = uint(*dec.Index) + if dec.Removed != nil { + l.Removed = *dec.Removed + } + return nil +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/gen_receipt_json.go b/vendor/github.com/getamis/go-ethereum/core/types/gen_receipt_json.go new file mode 100644 index 00000000..edbd64ba --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/gen_receipt_json.go @@ -0,0 +1,77 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package types + +import ( + "encoding/json" + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +func (r Receipt) MarshalJSON() ([]byte, error) { + type Receipt struct { + PostState hexutil.Bytes `json:"root" gencodec:"required"` + CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"` + Bloom Bloom `json:"logsBloom" gencodec:"required"` + Logs []*Log `json:"logs" gencodec:"required"` + TxHash common.Hash `json:"transactionHash" gencodec:"required"` + ContractAddress common.Address `json:"contractAddress"` + GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"` + } + var enc Receipt + enc.PostState = r.PostState + enc.CumulativeGasUsed = (*hexutil.Big)(r.CumulativeGasUsed) + enc.Bloom = r.Bloom + enc.Logs = r.Logs + enc.TxHash = r.TxHash + enc.ContractAddress = r.ContractAddress + enc.GasUsed = (*hexutil.Big)(r.GasUsed) + return json.Marshal(&enc) +} + +func (r *Receipt) UnmarshalJSON(input []byte) error { + type Receipt struct { + PostState hexutil.Bytes `json:"root" gencodec:"required"` + CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"` + Bloom *Bloom `json:"logsBloom" gencodec:"required"` + Logs []*Log `json:"logs" gencodec:"required"` + TxHash *common.Hash `json:"transactionHash" gencodec:"required"` + ContractAddress *common.Address `json:"contractAddress"` + GasUsed *hexutil.Big `json:"gasUsed" gencodec:"required"` + } + var dec Receipt + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.PostState == nil { + return errors.New("missing required field 'root' for Receipt") + } + r.PostState = dec.PostState + if dec.CumulativeGasUsed == nil { + return errors.New("missing required field 'cumulativeGasUsed' for Receipt") + } + r.CumulativeGasUsed = (*big.Int)(dec.CumulativeGasUsed) + if dec.Bloom == nil { + return errors.New("missing required field 'logsBloom' for Receipt") + } + r.Bloom = *dec.Bloom + if dec.Logs == nil { + return errors.New("missing required field 'logs' for Receipt") + } + r.Logs = dec.Logs + if dec.TxHash == nil { + return errors.New("missing required field 'transactionHash' for Receipt") + } + r.TxHash = *dec.TxHash + if dec.ContractAddress != nil { + r.ContractAddress = *dec.ContractAddress + } + if dec.GasUsed == nil { + return errors.New("missing required field 'gasUsed' for Receipt") + } + r.GasUsed = (*big.Int)(dec.GasUsed) + return nil +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/gen_tx_json.go b/vendor/github.com/getamis/go-ethereum/core/types/gen_tx_json.go new file mode 100644 index 00000000..4fb658e0 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/gen_tx_json.go @@ -0,0 +1,97 @@ +// Code generated by github.com/fjl/gencodec. DO NOT EDIT. + +package types + +import ( + "encoding/json" + "errors" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +func (t txdata) MarshalJSON() ([]byte, error) { + type txdata struct { + AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"` + Price *hexutil.Big `json:"gasPrice" gencodec:"required"` + GasLimit *hexutil.Big `json:"gas" gencodec:"required"` + Recipient *common.Address `json:"to" rlp:"nil"` + Amount *hexutil.Big `json:"value" gencodec:"required"` + Payload hexutil.Bytes `json:"input" gencodec:"required"` + V *hexutil.Big `json:"v" gencodec:"required"` + R *hexutil.Big `json:"r" gencodec:"required"` + S *hexutil.Big `json:"s" gencodec:"required"` + Hash *common.Hash `json:"hash" rlp:"-"` + } + var enc txdata + enc.AccountNonce = hexutil.Uint64(t.AccountNonce) + enc.Price = (*hexutil.Big)(t.Price) + enc.GasLimit = (*hexutil.Big)(t.GasLimit) + enc.Recipient = t.Recipient + enc.Amount = (*hexutil.Big)(t.Amount) + enc.Payload = t.Payload + enc.V = (*hexutil.Big)(t.V) + enc.R = (*hexutil.Big)(t.R) + enc.S = (*hexutil.Big)(t.S) + enc.Hash = t.Hash + return json.Marshal(&enc) +} + +func (t *txdata) UnmarshalJSON(input []byte) error { + type txdata struct { + AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"` + Price *hexutil.Big `json:"gasPrice" gencodec:"required"` + GasLimit *hexutil.Big `json:"gas" gencodec:"required"` + Recipient *common.Address `json:"to" rlp:"nil"` + Amount *hexutil.Big `json:"value" gencodec:"required"` + Payload hexutil.Bytes `json:"input" gencodec:"required"` + V *hexutil.Big `json:"v" gencodec:"required"` + R *hexutil.Big `json:"r" gencodec:"required"` + S *hexutil.Big `json:"s" gencodec:"required"` + Hash *common.Hash `json:"hash" rlp:"-"` + } + var dec txdata + if err := json.Unmarshal(input, &dec); err != nil { + return err + } + if dec.AccountNonce == nil { + return errors.New("missing required field 'nonce' for txdata") + } + t.AccountNonce = uint64(*dec.AccountNonce) + if dec.Price == nil { + return errors.New("missing required field 'gasPrice' for txdata") + } + t.Price = (*big.Int)(dec.Price) + if dec.GasLimit == nil { + return errors.New("missing required field 'gas' for txdata") + } + t.GasLimit = (*big.Int)(dec.GasLimit) + if dec.Recipient != nil { + t.Recipient = dec.Recipient + } + if dec.Amount == nil { + return errors.New("missing required field 'value' for txdata") + } + t.Amount = (*big.Int)(dec.Amount) + if dec.Payload == nil { + return errors.New("missing required field 'input' for txdata") + } + t.Payload = dec.Payload + if dec.V == nil { + return errors.New("missing required field 'v' for txdata") + } + t.V = (*big.Int)(dec.V) + if dec.R == nil { + return errors.New("missing required field 'r' for txdata") + } + t.R = (*big.Int)(dec.R) + if dec.S == nil { + return errors.New("missing required field 's' for txdata") + } + t.S = (*big.Int)(dec.S) + if dec.Hash != nil { + t.Hash = dec.Hash + } + return nil +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/istanbul.go b/vendor/github.com/getamis/go-ethereum/core/types/istanbul.go new file mode 100644 index 00000000..2fc5cf1e --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/istanbul.go @@ -0,0 +1,107 @@ +// Copyright 2017 AMIS Technologies +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "errors" + "io" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rlp" +) + +var ( + // The IstanbulDigest represents a constant of "Istanbul practical byzantine fault tolerance". + IstanbulDigest = common.HexToHash("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365") + + IstanbulExtraVanity = 32 // Fixed number of extra-data bytes reserved for validator vanity + IstanbulExtraSeal = 65 // Fixed number of extra-data bytes reserved for validator seal + + // ErrInvalidIstanbulHeaderExtra is returned if the header extra-data is less than 32 + // or the header extra can not decode + ErrInvalidIstanbulHeaderExtra = errors.New("Invalid istanbul header extra-data") +) + +type IstanbulExtra struct { + Validators []common.Address + Seal []byte + CommittedSeal [][]byte +} + +// EncodeRLP serializes ist into the Ethereum RLP format. +func (ist *IstanbulExtra) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, []interface{}{ + ist.Validators, + ist.Seal, + ist.CommittedSeal, + }) +} + +// DecodeRLP implements rlp.Decoder, and load the istanbul fields from a RLP stream. +func (ist *IstanbulExtra) DecodeRLP(s *rlp.Stream) error { + var istanbulExtra struct { + Validators []common.Address + Seal []byte + CommittedSeal [][]byte + } + if err := s.Decode(&istanbulExtra); err != nil { + return err + } + ist.Validators, ist.Seal, ist.CommittedSeal = istanbulExtra.Validators, istanbulExtra.Seal, istanbulExtra.CommittedSeal + return nil +} + +// ExtractToIstanbulExtra extracts all values of the IstanbulExtra from the header. It returns an +// error if the passed length of header extra-data is less than 32 or the header extra can not +// decode. +func ExtractIstanbulExtra(h *Header) (*IstanbulExtra, error) { + if len(h.Extra) < IstanbulExtraVanity { + return nil, ErrInvalidIstanbulHeaderExtra + } + + var istanbulExtra *IstanbulExtra + err := rlp.DecodeBytes(h.Extra[IstanbulExtraVanity:], &istanbulExtra) + if err != nil { + return nil, err + } + return istanbulExtra, nil +} + +// IstanbulFilteredHeader returns a filtered header which some information (like seal, committed seals) +// are clean to fulfill the Istanbul hash rules. It returns nil if the extra data of header cannot be +// decoded/encoded by rlp. +func IstanbulFilteredHeader(h *Header, keepSeal bool) *Header { + newHeader := CopyHeader(h) + istanbulExtra, err := ExtractIstanbulExtra(newHeader) + if err != nil { + return nil + } + + if !keepSeal { + istanbulExtra.Seal = []byte{} + } + istanbulExtra.CommittedSeal = [][]byte{} + + payload, err := rlp.EncodeToBytes(&istanbulExtra) + if err != nil { + return nil + } + + newHeader.Extra = append(newHeader.Extra[:IstanbulExtraVanity], payload...) + + return newHeader +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/log.go b/vendor/github.com/getamis/go-ethereum/core/types/log.go new file mode 100644 index 00000000..be5de38d --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/log.go @@ -0,0 +1,137 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "fmt" + "io" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rlp" +) + +//go:generate gencodec -type Log -field-override logMarshaling -out gen_log_json.go + +// Log represents a contract log event. These events are generated by the LOG opcode and +// stored/indexed by the node. +type Log struct { + // Consensus fields: + // address of the contract that generated the event + Address common.Address `json:"address" gencodec:"required"` + // list of topics provided by the contract. + Topics []common.Hash `json:"topics" gencodec:"required"` + // supplied by the contract, usually ABI-encoded + Data []byte `json:"data" gencodec:"required"` + + // Derived fields. These fields are filled in by the node + // but not secured by consensus. + // block in which the transaction was included + BlockNumber uint64 `json:"blockNumber"` + // hash of the transaction + TxHash common.Hash `json:"transactionHash" gencodec:"required"` + // index of the transaction in the block + TxIndex uint `json:"transactionIndex" gencodec:"required"` + // hash of the block in which the transaction was included + BlockHash common.Hash `json:"blockHash"` + // index of the log in the receipt + Index uint `json:"logIndex" gencodec:"required"` + + // The Removed field is true if this log was reverted due to a chain reorganisation. + // You must pay attention to this field if you receive logs through a filter query. + Removed bool `json:"removed"` +} + +type logMarshaling struct { + Data hexutil.Bytes + BlockNumber hexutil.Uint64 + TxIndex hexutil.Uint + Index hexutil.Uint +} + +type rlpLog struct { + Address common.Address + Topics []common.Hash + Data []byte +} + +type rlpStorageLog struct { + Address common.Address + Topics []common.Hash + Data []byte + BlockNumber uint64 + TxHash common.Hash + TxIndex uint + BlockHash common.Hash + Index uint +} + +// EncodeRLP implements rlp.Encoder. +func (l *Log) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data}) +} + +// DecodeRLP implements rlp.Decoder. +func (l *Log) DecodeRLP(s *rlp.Stream) error { + var dec rlpLog + err := s.Decode(&dec) + if err == nil { + l.Address, l.Topics, l.Data = dec.Address, dec.Topics, dec.Data + } + return err +} + +func (l *Log) String() string { + return fmt.Sprintf(`log: %x %x %x %x %d %x %d`, l.Address, l.Topics, l.Data, l.TxHash, l.TxIndex, l.BlockHash, l.Index) +} + +// LogForStorage is a wrapper around a Log that flattens and parses the entire content of +// a log including non-consensus fields. +type LogForStorage Log + +// EncodeRLP implements rlp.Encoder. +func (l *LogForStorage) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, rlpStorageLog{ + Address: l.Address, + Topics: l.Topics, + Data: l.Data, + BlockNumber: l.BlockNumber, + TxHash: l.TxHash, + TxIndex: l.TxIndex, + BlockHash: l.BlockHash, + Index: l.Index, + }) +} + +// DecodeRLP implements rlp.Decoder. +func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error { + var dec rlpStorageLog + err := s.Decode(&dec) + if err == nil { + *l = LogForStorage{ + Address: dec.Address, + Topics: dec.Topics, + Data: dec.Data, + BlockNumber: dec.BlockNumber, + TxHash: dec.TxHash, + TxIndex: dec.TxIndex, + BlockHash: dec.BlockHash, + Index: dec.Index, + } + } + return err +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/receipt.go b/vendor/github.com/getamis/go-ethereum/core/types/receipt.go new file mode 100644 index 00000000..ef6f6a2b --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/receipt.go @@ -0,0 +1,137 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "fmt" + "io" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rlp" +) + +//go:generate gencodec -type Receipt -field-override receiptMarshaling -out gen_receipt_json.go + +// Receipt represents the results of a transaction. +type Receipt struct { + // Consensus fields + PostState []byte `json:"root" gencodec:"required"` + CumulativeGasUsed *big.Int `json:"cumulativeGasUsed" gencodec:"required"` + Bloom Bloom `json:"logsBloom" gencodec:"required"` + Logs []*Log `json:"logs" gencodec:"required"` + + // Implementation fields (don't reorder!) + TxHash common.Hash `json:"transactionHash" gencodec:"required"` + ContractAddress common.Address `json:"contractAddress"` + GasUsed *big.Int `json:"gasUsed" gencodec:"required"` +} + +type receiptMarshaling struct { + PostState hexutil.Bytes + CumulativeGasUsed *hexutil.Big + GasUsed *hexutil.Big +} + +// NewReceipt creates a barebone transaction receipt, copying the init fields. +func NewReceipt(root []byte, cumulativeGasUsed *big.Int) *Receipt { + return &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumulativeGasUsed)} +} + +// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt +// into an RLP stream. +func (r *Receipt) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs}) +} + +// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt +// from an RLP stream. +func (r *Receipt) DecodeRLP(s *rlp.Stream) error { + var receipt struct { + PostState []byte + CumulativeGasUsed *big.Int + Bloom Bloom + Logs []*Log + } + if err := s.Decode(&receipt); err != nil { + return err + } + r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs = receipt.PostState, receipt.CumulativeGasUsed, receipt.Bloom, receipt.Logs + return nil +} + +// String implements the Stringer interface. +func (r *Receipt) String() string { + return fmt.Sprintf("receipt{med=%x cgas=%v bloom=%x logs=%v}", r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs) +} + +// ReceiptForStorage is a wrapper around a Receipt that flattens and parses the +// entire content of a receipt, as opposed to only the consensus fields originally. +type ReceiptForStorage Receipt + +// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt +// into an RLP stream. +func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error { + logs := make([]*LogForStorage, len(r.Logs)) + for i, log := range r.Logs { + logs[i] = (*LogForStorage)(log) + } + return rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, logs, r.GasUsed}) +} + +// DecodeRLP implements rlp.Decoder, and loads both consensus and implementation +// fields of a receipt from an RLP stream. +func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error { + var receipt struct { + PostState []byte + CumulativeGasUsed *big.Int + Bloom Bloom + TxHash common.Hash + ContractAddress common.Address + Logs []*LogForStorage + GasUsed *big.Int + } + if err := s.Decode(&receipt); err != nil { + return err + } + // Assign the consensus fields + r.PostState, r.CumulativeGasUsed, r.Bloom = receipt.PostState, receipt.CumulativeGasUsed, receipt.Bloom + r.Logs = make([]*Log, len(receipt.Logs)) + for i, log := range receipt.Logs { + r.Logs[i] = (*Log)(log) + } + // Assign the implementation fields + r.TxHash, r.ContractAddress, r.GasUsed = receipt.TxHash, receipt.ContractAddress, receipt.GasUsed + + return nil +} + +// Receipts is a wrapper around a Receipt array to implement DerivableList. +type Receipts []*Receipt + +// Len returns the number of receipts in this list. +func (r Receipts) Len() int { return len(r) } + +// GetRlp returns the RLP encoding of one receipt from the list. +func (r Receipts) GetRlp(i int) []byte { + bytes, err := rlp.EncodeToBytes(r[i]) + if err != nil { + panic(err) + } + return bytes +} diff --git a/vendor/github.com/getamis/go-ethereum/core/types/transaction.go b/vendor/github.com/getamis/go-ethereum/core/types/transaction.go new file mode 100644 index 00000000..8e108b2a --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/transaction.go @@ -0,0 +1,469 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "container/heap" + "errors" + "fmt" + "io" + "math/big" + "sync/atomic" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" +) + +//go:generate gencodec -type txdata -field-override txdataMarshaling -out gen_tx_json.go + +var ( + ErrInvalidSig = errors.New("invalid transaction v, r, s values") + errNoSigner = errors.New("missing signing methods") +) + +// deriveSigner makes a *best* guess about which signer to use. +func deriveSigner(V *big.Int) Signer { + if V.Sign() != 0 && isProtectedV(V) { + return NewEIP155Signer(deriveChainId(V)) + } else { + return HomesteadSigner{} + } +} + +type Transaction struct { + data txdata + // caches + hash atomic.Value + size atomic.Value + from atomic.Value +} + +type txdata struct { + AccountNonce uint64 `json:"nonce" gencodec:"required"` + Price *big.Int `json:"gasPrice" gencodec:"required"` + GasLimit *big.Int `json:"gas" gencodec:"required"` + Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation + Amount *big.Int `json:"value" gencodec:"required"` + Payload []byte `json:"input" gencodec:"required"` + + // Signature values + V *big.Int `json:"v" gencodec:"required"` + R *big.Int `json:"r" gencodec:"required"` + S *big.Int `json:"s" gencodec:"required"` + + // This is only used when marshaling to JSON. + Hash *common.Hash `json:"hash" rlp:"-"` +} + +type txdataMarshaling struct { + AccountNonce hexutil.Uint64 + Price *hexutil.Big + GasLimit *hexutil.Big + Amount *hexutil.Big + Payload hexutil.Bytes + V *hexutil.Big + R *hexutil.Big + S *hexutil.Big +} + +func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction { + return newTransaction(nonce, &to, amount, gasLimit, gasPrice, data) +} + +func NewContractCreation(nonce uint64, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction { + return newTransaction(nonce, nil, amount, gasLimit, gasPrice, data) +} + +func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction { + if len(data) > 0 { + data = common.CopyBytes(data) + } + d := txdata{ + AccountNonce: nonce, + Recipient: to, + Payload: data, + Amount: new(big.Int), + GasLimit: new(big.Int), + Price: new(big.Int), + V: new(big.Int), + R: new(big.Int), + S: new(big.Int), + } + if amount != nil { + d.Amount.Set(amount) + } + if gasLimit != nil { + d.GasLimit.Set(gasLimit) + } + if gasPrice != nil { + d.Price.Set(gasPrice) + } + + return &Transaction{data: d} +} + +// ChainId returns which chain id this transaction was signed for (if at all) +func (tx *Transaction) ChainId() *big.Int { + return deriveChainId(tx.data.V) +} + +// Protected returns whether the transaction is protected from replay protection. +func (tx *Transaction) Protected() bool { + return isProtectedV(tx.data.V) +} + +func isProtectedV(V *big.Int) bool { + if V.BitLen() <= 8 { + v := V.Uint64() + return v != 27 && v != 28 + } + // anything not 27 or 28 are considered unprotected + return true +} + +// DecodeRLP implements rlp.Encoder +func (tx *Transaction) EncodeRLP(w io.Writer) error { + return rlp.Encode(w, &tx.data) +} + +// DecodeRLP implements rlp.Decoder +func (tx *Transaction) DecodeRLP(s *rlp.Stream) error { + _, size, _ := s.Kind() + err := s.Decode(&tx.data) + if err == nil { + tx.size.Store(common.StorageSize(rlp.ListSize(size))) + } + + return err +} + +func (tx *Transaction) MarshalJSON() ([]byte, error) { + hash := tx.Hash() + data := tx.data + data.Hash = &hash + return data.MarshalJSON() +} + +// UnmarshalJSON decodes the web3 RPC transaction format. +func (tx *Transaction) UnmarshalJSON(input []byte) error { + var dec txdata + if err := dec.UnmarshalJSON(input); err != nil { + return err + } + var V byte + if isProtectedV(dec.V) { + chainId := deriveChainId(dec.V).Uint64() + V = byte(dec.V.Uint64() - 35 - 2*chainId) + } else { + V = byte(dec.V.Uint64() - 27) + } + if !crypto.ValidateSignatureValues(V, dec.R, dec.S, false) { + return ErrInvalidSig + } + *tx = Transaction{data: dec} + return nil +} + +func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) } +func (tx *Transaction) Gas() *big.Int { return new(big.Int).Set(tx.data.GasLimit) } +func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) } +func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) } +func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce } +func (tx *Transaction) CheckNonce() bool { return true } + +// To returns the recipient address of the transaction. +// It returns nil if the transaction is a contract creation. +func (tx *Transaction) To() *common.Address { + if tx.data.Recipient == nil { + return nil + } else { + to := *tx.data.Recipient + return &to + } +} + +// Hash hashes the RLP encoding of tx. +// It uniquely identifies the transaction. +func (tx *Transaction) Hash() common.Hash { + if hash := tx.hash.Load(); hash != nil { + return hash.(common.Hash) + } + v := rlpHash(tx) + tx.hash.Store(v) + return v +} + +// SigHash returns the hash to be signed by the sender. +// It does not uniquely identify the transaction. +func (tx *Transaction) SigHash(signer Signer) common.Hash { + return signer.Hash(tx) +} + +func (tx *Transaction) Size() common.StorageSize { + if size := tx.size.Load(); size != nil { + return size.(common.StorageSize) + } + c := writeCounter(0) + rlp.Encode(&c, &tx.data) + tx.size.Store(common.StorageSize(c)) + return common.StorageSize(c) +} + +// AsMessage returns the transaction as a core.Message. +// +// AsMessage requires a signer to derive the sender. +// +// XXX Rename message to something less arbitrary? +func (tx *Transaction) AsMessage(s Signer) (Message, error) { + msg := Message{ + nonce: tx.data.AccountNonce, + price: new(big.Int).Set(tx.data.Price), + gasLimit: new(big.Int).Set(tx.data.GasLimit), + to: tx.data.Recipient, + amount: tx.data.Amount, + data: tx.data.Payload, + checkNonce: true, + } + + var err error + msg.from, err = Sender(s, tx) + return msg, err +} + +// WithSignature returns a new transaction with the given signature. +// This signature needs to be formatted as described in the yellow paper (v+27). +func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) { + return signer.WithSignature(tx, sig) +} + +// Cost returns amount + gasprice * gaslimit. +func (tx *Transaction) Cost() *big.Int { + total := new(big.Int).Mul(tx.data.Price, tx.data.GasLimit) + total.Add(total, tx.data.Amount) + return total +} + +func (tx *Transaction) RawSignatureValues() (*big.Int, *big.Int, *big.Int) { + return tx.data.V, tx.data.R, tx.data.S +} + +func (tx *Transaction) String() string { + var from, to string + if tx.data.V != nil { + // make a best guess about the signer and use that to derive + // the sender. + signer := deriveSigner(tx.data.V) + if f, err := Sender(signer, tx); err != nil { // derive but don't cache + from = "[invalid sender: invalid sig]" + } else { + from = fmt.Sprintf("%x", f[:]) + } + } else { + from = "[invalid sender: nil V field]" + } + + if tx.data.Recipient == nil { + to = "[contract creation]" + } else { + to = fmt.Sprintf("%x", tx.data.Recipient[:]) + } + enc, _ := rlp.EncodeToBytes(&tx.data) + return fmt.Sprintf(` + TX(%x) + Contract: %v + From: %s + To: %s + Nonce: %v + GasPrice: %#x + GasLimit %#x + Value: %#x + Data: 0x%x + V: %#x + R: %#x + S: %#x + Hex: %x +`, + tx.Hash(), + len(tx.data.Recipient) == 0, + from, + to, + tx.data.AccountNonce, + tx.data.Price, + tx.data.GasLimit, + tx.data.Amount, + tx.data.Payload, + tx.data.V, + tx.data.R, + tx.data.S, + enc, + ) +} + +// Transaction slice type for basic sorting. +type Transactions []*Transaction + +// Len returns the length of s +func (s Transactions) Len() int { return len(s) } + +// Swap swaps the i'th and the j'th element in s +func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// GetRlp implements Rlpable and returns the i'th element of s in rlp +func (s Transactions) GetRlp(i int) []byte { + enc, _ := rlp.EncodeToBytes(s[i]) + return enc +} + +// Returns a new set t which is the difference between a to b +func TxDifference(a, b Transactions) (keep Transactions) { + keep = make(Transactions, 0, len(a)) + + remove := make(map[common.Hash]struct{}) + for _, tx := range b { + remove[tx.Hash()] = struct{}{} + } + + for _, tx := range a { + if _, ok := remove[tx.Hash()]; !ok { + keep = append(keep, tx) + } + } + + return keep +} + +// TxByNonce implements the sort interface to allow sorting a list of transactions +// by their nonces. This is usually only useful for sorting transactions from a +// single account, otherwise a nonce comparison doesn't make much sense. +type TxByNonce Transactions + +func (s TxByNonce) Len() int { return len(s) } +func (s TxByNonce) Less(i, j int) bool { return s[i].data.AccountNonce < s[j].data.AccountNonce } +func (s TxByNonce) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// TxByPrice implements both the sort and the heap interface, making it useful +// for all at once sorting as well as individually adding and removing elements. +type TxByPrice Transactions + +func (s TxByPrice) Len() int { return len(s) } +func (s TxByPrice) Less(i, j int) bool { return s[i].data.Price.Cmp(s[j].data.Price) > 0 } +func (s TxByPrice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func (s *TxByPrice) Push(x interface{}) { + *s = append(*s, x.(*Transaction)) +} + +func (s *TxByPrice) Pop() interface{} { + old := *s + n := len(old) + x := old[n-1] + *s = old[0 : n-1] + return x +} + +// TransactionsByPriceAndNonce represents a set of transactions that can return +// transactions in a profit-maximising sorted order, while supporting removing +// entire batches of transactions for non-executable accounts. +type TransactionsByPriceAndNonce struct { + txs map[common.Address]Transactions // Per account nonce-sorted list of transactions + heads TxByPrice // Next transaction for each unique account (price heap) +} + +// NewTransactionsByPriceAndNonce creates a transaction set that can retrieve +// price sorted transactions in a nonce-honouring way. +// +// Note, the input map is reowned so the caller should not interact any more with +// if after providng it to the constructor. +func NewTransactionsByPriceAndNonce(txs map[common.Address]Transactions) *TransactionsByPriceAndNonce { + // Initialize a price based heap with the head transactions + heads := make(TxByPrice, 0, len(txs)) + for acc, accTxs := range txs { + heads = append(heads, accTxs[0]) + txs[acc] = accTxs[1:] + } + heap.Init(&heads) + + // Assemble and return the transaction set + return &TransactionsByPriceAndNonce{ + txs: txs, + heads: heads, + } +} + +// Peek returns the next transaction by price. +func (t *TransactionsByPriceAndNonce) Peek() *Transaction { + if len(t.heads) == 0 { + return nil + } + return t.heads[0] +} + +// Shift replaces the current best head with the next one from the same account. +func (t *TransactionsByPriceAndNonce) Shift() { + signer := deriveSigner(t.heads[0].data.V) + // derive signer but don't cache. + acc, _ := Sender(signer, t.heads[0]) // we only sort valid txs so this cannot fail + if txs, ok := t.txs[acc]; ok && len(txs) > 0 { + t.heads[0], t.txs[acc] = txs[0], txs[1:] + heap.Fix(&t.heads, 0) + } else { + heap.Pop(&t.heads) + } +} + +// Pop removes the best transaction, *not* replacing it with the next one from +// the same account. This should be used when a transaction cannot be executed +// and hence all subsequent ones should be discarded from the same account. +func (t *TransactionsByPriceAndNonce) Pop() { + heap.Pop(&t.heads) +} + +// Message is a fully derived transaction and implements core.Message +// +// NOTE: In a future PR this will be removed. +type Message struct { + to *common.Address + from common.Address + nonce uint64 + amount, price, gasLimit *big.Int + data []byte + checkNonce bool +} + +func NewMessage(from common.Address, to *common.Address, nonce uint64, amount, gasLimit, price *big.Int, data []byte, checkNonce bool) Message { + return Message{ + from: from, + to: to, + nonce: nonce, + amount: amount, + price: price, + gasLimit: gasLimit, + data: data, + checkNonce: checkNonce, + } +} + +func (m Message) From() common.Address { return m.from } +func (m Message) To() *common.Address { return m.to } +func (m Message) GasPrice() *big.Int { return m.price } +func (m Message) Value() *big.Int { return m.amount } +func (m Message) Gas() *big.Int { return m.gasLimit } +func (m Message) Nonce() uint64 { return m.nonce } +func (m Message) Data() []byte { return m.data } +func (m Message) CheckNonce() bool { return m.checkNonce } diff --git a/vendor/github.com/getamis/go-ethereum/core/types/transaction_signing.go b/vendor/github.com/getamis/go-ethereum/core/types/transaction_signing.go new file mode 100644 index 00000000..b0f3275b --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/core/types/transaction_signing.go @@ -0,0 +1,320 @@ +// Copyright 2016 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "crypto/ecdsa" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" +) + +var ( + ErrInvalidChainId = errors.New("invalid chaid id for signer") + + errAbstractSigner = errors.New("abstract signer") + abstractSignerAddress = common.HexToAddress("ffffffffffffffffffffffffffffffffffffffff") +) + +// sigCache is used to cache the derived sender and contains +// the signer used to derive it. +type sigCache struct { + signer Signer + from common.Address +} + +// MakeSigner returns a Signer based on the given chain config and block number. +func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer { + var signer Signer + switch { + case config.IsEIP155(blockNumber): + signer = NewEIP155Signer(config.ChainId) + case config.IsHomestead(blockNumber): + signer = HomesteadSigner{} + default: + signer = FrontierSigner{} + } + return signer +} + +// SignTx signs the transaction using the given signer and private key +func SignTx(tx *Transaction, s Signer, prv *ecdsa.PrivateKey) (*Transaction, error) { + h := s.Hash(tx) + sig, err := crypto.Sign(h[:], prv) + if err != nil { + return nil, err + } + return s.WithSignature(tx, sig) +} + +// Sender derives the sender from the tx using the signer derivation +// functions. + +// Sender returns the address derived from the signature (V, R, S) using secp256k1 +// elliptic curve and an error if it failed deriving or upon an incorrect +// signature. +// +// Sender may cache the address, allowing it to be used regardless of +// signing method. The cache is invalidated if the cached signer does +// not match the signer used in the current call. +func Sender(signer Signer, tx *Transaction) (common.Address, error) { + if sc := tx.from.Load(); sc != nil { + sigCache := sc.(sigCache) + // If the signer used to derive from in a previous + // call is not the same as used current, invalidate + // the cache. + if sigCache.signer.Equal(signer) { + return sigCache.from, nil + } + } + + pubkey, err := signer.PublicKey(tx) + if err != nil { + return common.Address{}, err + } + var addr common.Address + copy(addr[:], crypto.Keccak256(pubkey[1:])[12:]) + tx.from.Store(sigCache{signer: signer, from: addr}) + return addr, nil +} + +type Signer interface { + // Hash returns the rlp encoded hash for signatures + Hash(tx *Transaction) common.Hash + // PubilcKey returns the public key derived from the signature + PublicKey(tx *Transaction) ([]byte, error) + // WithSignature returns a copy of the transaction with the given signature. + // The signature must be encoded in [R || S || V] format where V is 0 or 1. + WithSignature(tx *Transaction, sig []byte) (*Transaction, error) + // Checks for equality on the signers + Equal(Signer) bool +} + +// EIP155Transaction implements TransactionInterface using the +// EIP155 rules +type EIP155Signer struct { + HomesteadSigner + + chainId, chainIdMul *big.Int +} + +func NewEIP155Signer(chainId *big.Int) EIP155Signer { + if chainId == nil { + chainId = new(big.Int) + } + return EIP155Signer{ + chainId: chainId, + chainIdMul: new(big.Int).Mul(chainId, big.NewInt(2)), + } +} + +func (s EIP155Signer) Equal(s2 Signer) bool { + eip155, ok := s2.(EIP155Signer) + return ok && eip155.chainId.Cmp(s.chainId) == 0 +} + +func (s EIP155Signer) PublicKey(tx *Transaction) ([]byte, error) { + // if the transaction is not protected fall back to homestead signer + if !tx.Protected() { + return (HomesteadSigner{}).PublicKey(tx) + } + + if tx.ChainId().Cmp(s.chainId) != 0 { + return nil, ErrInvalidChainId + } + + V := byte(new(big.Int).Sub(tx.data.V, s.chainIdMul).Uint64() - 35) + if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, true) { + return nil, ErrInvalidSig + } + // encode the signature in uncompressed format + R, S := tx.data.R.Bytes(), tx.data.S.Bytes() + sig := make([]byte, 65) + copy(sig[32-len(R):32], R) + copy(sig[64-len(S):64], S) + sig[64] = V + + // recover the public key from the signature + hash := s.Hash(tx) + pub, err := crypto.Ecrecover(hash[:], sig) + if err != nil { + return nil, err + } + if len(pub) == 0 || pub[0] != 4 { + return nil, errors.New("invalid public key") + } + return pub, nil +} + +// WithSignature returns a new transaction with the given signature. This signature +// needs to be in the [R || S || V] format where V is 0 or 1. +func (s EIP155Signer) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) { + if len(sig) != 65 { + panic(fmt.Sprintf("wrong size for signature: got %d, want 65", len(sig))) + } + + cpy := &Transaction{data: tx.data} + cpy.data.R = new(big.Int).SetBytes(sig[:32]) + cpy.data.S = new(big.Int).SetBytes(sig[32:64]) + cpy.data.V = new(big.Int).SetBytes([]byte{sig[64]}) + if s.chainId.Sign() != 0 { + cpy.data.V = big.NewInt(int64(sig[64] + 35)) + cpy.data.V.Add(cpy.data.V, s.chainIdMul) + } + return cpy, nil +} + +// Hash returns the hash to be signed by the sender. +// It does not uniquely identify the transaction. +func (s EIP155Signer) Hash(tx *Transaction) common.Hash { + return rlpHash([]interface{}{ + tx.data.AccountNonce, + tx.data.Price, + tx.data.GasLimit, + tx.data.Recipient, + tx.data.Amount, + tx.data.Payload, + s.chainId, uint(0), uint(0), + }) +} + +// HomesteadTransaction implements TransactionInterface using the +// homestead rules. +type HomesteadSigner struct{ FrontierSigner } + +func (s HomesteadSigner) Equal(s2 Signer) bool { + _, ok := s2.(HomesteadSigner) + return ok +} + +// WithSignature returns a new transaction with the given signature. This signature +// needs to be in the [R || S || V] format where V is 0 or 1. +func (hs HomesteadSigner) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) { + if len(sig) != 65 { + panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig))) + } + cpy := &Transaction{data: tx.data} + cpy.data.R = new(big.Int).SetBytes(sig[:32]) + cpy.data.S = new(big.Int).SetBytes(sig[32:64]) + cpy.data.V = new(big.Int).SetBytes([]byte{sig[64] + 27}) + return cpy, nil +} + +func (hs HomesteadSigner) PublicKey(tx *Transaction) ([]byte, error) { + if tx.data.V.BitLen() > 8 { + return nil, ErrInvalidSig + } + V := byte(tx.data.V.Uint64() - 27) + if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, true) { + return nil, ErrInvalidSig + } + // encode the snature in uncompressed format + r, s := tx.data.R.Bytes(), tx.data.S.Bytes() + sig := make([]byte, 65) + copy(sig[32-len(r):32], r) + copy(sig[64-len(s):64], s) + sig[64] = V + + // recover the public key from the snature + hash := hs.Hash(tx) + pub, err := crypto.Ecrecover(hash[:], sig) + if err != nil { + return nil, err + } + if len(pub) == 0 || pub[0] != 4 { + return nil, errors.New("invalid public key") + } + return pub, nil +} + +type FrontierSigner struct{} + +func (s FrontierSigner) Equal(s2 Signer) bool { + _, ok := s2.(FrontierSigner) + return ok +} + +// WithSignature returns a new transaction with the given signature. This signature +// needs to be in the [R || S || V] format where V is 0 or 1. +func (fs FrontierSigner) WithSignature(tx *Transaction, sig []byte) (*Transaction, error) { + if len(sig) != 65 { + panic(fmt.Sprintf("wrong size for snature: got %d, want 65", len(sig))) + } + cpy := &Transaction{data: tx.data} + cpy.data.R = new(big.Int).SetBytes(sig[:32]) + cpy.data.S = new(big.Int).SetBytes(sig[32:64]) + cpy.data.V = new(big.Int).SetBytes([]byte{sig[64] + 27}) + return cpy, nil +} + +// Hash returns the hash to be sned by the sender. +// It does not uniquely identify the transaction. +func (fs FrontierSigner) Hash(tx *Transaction) common.Hash { + return rlpHash([]interface{}{ + tx.data.AccountNonce, + tx.data.Price, + tx.data.GasLimit, + tx.data.Recipient, + tx.data.Amount, + tx.data.Payload, + }) +} + +func (fs FrontierSigner) PublicKey(tx *Transaction) ([]byte, error) { + if tx.data.V.BitLen() > 8 { + return nil, ErrInvalidSig + } + + V := byte(tx.data.V.Uint64() - 27) + if !crypto.ValidateSignatureValues(V, tx.data.R, tx.data.S, false) { + return nil, ErrInvalidSig + } + // encode the snature in uncompressed format + r, s := tx.data.R.Bytes(), tx.data.S.Bytes() + sig := make([]byte, 65) + copy(sig[32-len(r):32], r) + copy(sig[64-len(s):64], s) + sig[64] = V + + // recover the public key from the snature + hash := fs.Hash(tx) + pub, err := crypto.Ecrecover(hash[:], sig) + if err != nil { + return nil, err + } + if len(pub) == 0 || pub[0] != 4 { + return nil, errors.New("invalid public key") + } + return pub, nil +} + +// deriveChainId derives the chain id from the given v parameter +func deriveChainId(v *big.Int) *big.Int { + if v.BitLen() <= 64 { + v := v.Uint64() + if v == 27 || v == 28 { + return new(big.Int) + } + return new(big.Int).SetUint64((v - 35) / 2) + } + v = new(big.Int).Sub(v, big.NewInt(35)) + return v.Div(v, big.NewInt(2)) +} diff --git a/vendor/github.com/getamis/go-ethereum/rlp/decode.go b/vendor/github.com/getamis/go-ethereum/rlp/decode.go new file mode 100644 index 00000000..78ccf627 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/rlp/decode.go @@ -0,0 +1,1041 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rlp + +import ( + "bufio" + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + "reflect" + "strings" +) + +var ( + errNoPointer = errors.New("rlp: interface given to Decode must be a pointer") + errDecodeIntoNil = errors.New("rlp: pointer given to Decode must not be nil") +) + +// Decoder is implemented by types that require custom RLP +// decoding rules or need to decode into private fields. +// +// The DecodeRLP method should read one value from the given +// Stream. It is not forbidden to read less or more, but it might +// be confusing. +type Decoder interface { + DecodeRLP(*Stream) error +} + +// Decode parses RLP-encoded data from r and stores the result in the +// value pointed to by val. Val must be a non-nil pointer. If r does +// not implement ByteReader, Decode will do its own buffering. +// +// Decode uses the following type-dependent decoding rules: +// +// If the type implements the Decoder interface, decode calls +// DecodeRLP. +// +// To decode into a pointer, Decode will decode into the value pointed +// to. If the pointer is nil, a new value of the pointer's element +// type is allocated. If the pointer is non-nil, the existing value +// will be reused. +// +// To decode into a struct, Decode expects the input to be an RLP +// list. The decoded elements of the list are assigned to each public +// field in the order given by the struct's definition. The input list +// must contain an element for each decoded field. Decode returns an +// error if there are too few or too many elements. +// +// The decoding of struct fields honours certain struct tags, "tail", +// "nil" and "-". +// +// The "-" tag ignores fields. +// +// For an explanation of "tail", see the example. +// +// The "nil" tag applies to pointer-typed fields and changes the decoding +// rules for the field such that input values of size zero decode as a nil +// pointer. This tag can be useful when decoding recursive types. +// +// type StructWithEmptyOK struct { +// Foo *[20]byte `rlp:"nil"` +// } +// +// To decode into a slice, the input must be a list and the resulting +// slice will contain the input elements in order. For byte slices, +// the input must be an RLP string. Array types decode similarly, with +// the additional restriction that the number of input elements (or +// bytes) must match the array's length. +// +// To decode into a Go string, the input must be an RLP string. The +// input bytes are taken as-is and will not necessarily be valid UTF-8. +// +// To decode into an unsigned integer type, the input must also be an RLP +// string. The bytes are interpreted as a big endian representation of +// the integer. If the RLP string is larger than the bit size of the +// type, Decode will return an error. Decode also supports *big.Int. +// There is no size limit for big integers. +// +// To decode into an interface value, Decode stores one of these +// in the value: +// +// []interface{}, for RLP lists +// []byte, for RLP strings +// +// Non-empty interface types are not supported, nor are booleans, +// signed integers, floating point numbers, maps, channels and +// functions. +// +// Note that Decode does not set an input limit for all readers +// and may be vulnerable to panics cause by huge value sizes. If +// you need an input limit, use +// +// NewStream(r, limit).Decode(val) +func Decode(r io.Reader, val interface{}) error { + // TODO: this could use a Stream from a pool. + return NewStream(r, 0).Decode(val) +} + +// DecodeBytes parses RLP data from b into val. +// Please see the documentation of Decode for the decoding rules. +// The input must contain exactly one value and no trailing data. +func DecodeBytes(b []byte, val interface{}) error { + // TODO: this could use a Stream from a pool. + r := bytes.NewReader(b) + if err := NewStream(r, uint64(len(b))).Decode(val); err != nil { + return err + } + if r.Len() > 0 { + return ErrMoreThanOneValue + } + return nil +} + +type decodeError struct { + msg string + typ reflect.Type + ctx []string +} + +func (err *decodeError) Error() string { + ctx := "" + if len(err.ctx) > 0 { + ctx = ", decoding into " + for i := len(err.ctx) - 1; i >= 0; i-- { + ctx += err.ctx[i] + } + } + return fmt.Sprintf("rlp: %s for %v%s", err.msg, err.typ, ctx) +} + +func wrapStreamError(err error, typ reflect.Type) error { + switch err { + case ErrCanonInt: + return &decodeError{msg: "non-canonical integer (leading zero bytes)", typ: typ} + case ErrCanonSize: + return &decodeError{msg: "non-canonical size information", typ: typ} + case ErrExpectedList: + return &decodeError{msg: "expected input list", typ: typ} + case ErrExpectedString: + return &decodeError{msg: "expected input string or byte", typ: typ} + case errUintOverflow: + return &decodeError{msg: "input string too long", typ: typ} + case errNotAtEOL: + return &decodeError{msg: "input list has too many elements", typ: typ} + } + return err +} + +func addErrorContext(err error, ctx string) error { + if decErr, ok := err.(*decodeError); ok { + decErr.ctx = append(decErr.ctx, ctx) + } + return err +} + +var ( + decoderInterface = reflect.TypeOf(new(Decoder)).Elem() + bigInt = reflect.TypeOf(big.Int{}) +) + +func makeDecoder(typ reflect.Type, tags tags) (dec decoder, err error) { + kind := typ.Kind() + switch { + case typ == rawValueType: + return decodeRawValue, nil + case typ.Implements(decoderInterface): + return decodeDecoder, nil + case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(decoderInterface): + return decodeDecoderNoPtr, nil + case typ.AssignableTo(reflect.PtrTo(bigInt)): + return decodeBigInt, nil + case typ.AssignableTo(bigInt): + return decodeBigIntNoPtr, nil + case isUint(kind): + return decodeUint, nil + case kind == reflect.Bool: + return decodeBool, nil + case kind == reflect.String: + return decodeString, nil + case kind == reflect.Slice || kind == reflect.Array: + return makeListDecoder(typ, tags) + case kind == reflect.Struct: + return makeStructDecoder(typ) + case kind == reflect.Ptr: + if tags.nilOK { + return makeOptionalPtrDecoder(typ) + } + return makePtrDecoder(typ) + case kind == reflect.Interface: + return decodeInterface, nil + default: + return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ) + } +} + +func decodeRawValue(s *Stream, val reflect.Value) error { + r, err := s.Raw() + if err != nil { + return err + } + val.SetBytes(r) + return nil +} + +func decodeUint(s *Stream, val reflect.Value) error { + typ := val.Type() + num, err := s.uint(typ.Bits()) + if err != nil { + return wrapStreamError(err, val.Type()) + } + val.SetUint(num) + return nil +} + +func decodeBool(s *Stream, val reflect.Value) error { + b, err := s.Bool() + if err != nil { + return wrapStreamError(err, val.Type()) + } + val.SetBool(b) + return nil +} + +func decodeString(s *Stream, val reflect.Value) error { + b, err := s.Bytes() + if err != nil { + return wrapStreamError(err, val.Type()) + } + val.SetString(string(b)) + return nil +} + +func decodeBigIntNoPtr(s *Stream, val reflect.Value) error { + return decodeBigInt(s, val.Addr()) +} + +func decodeBigInt(s *Stream, val reflect.Value) error { + b, err := s.Bytes() + if err != nil { + return wrapStreamError(err, val.Type()) + } + i := val.Interface().(*big.Int) + if i == nil { + i = new(big.Int) + val.Set(reflect.ValueOf(i)) + } + // Reject leading zero bytes + if len(b) > 0 && b[0] == 0 { + return wrapStreamError(ErrCanonInt, val.Type()) + } + i.SetBytes(b) + return nil +} + +func makeListDecoder(typ reflect.Type, tag tags) (decoder, error) { + etype := typ.Elem() + if etype.Kind() == reflect.Uint8 && !reflect.PtrTo(etype).Implements(decoderInterface) { + if typ.Kind() == reflect.Array { + return decodeByteArray, nil + } else { + return decodeByteSlice, nil + } + } + etypeinfo, err := cachedTypeInfo1(etype, tags{}) + if err != nil { + return nil, err + } + var dec decoder + switch { + case typ.Kind() == reflect.Array: + dec = func(s *Stream, val reflect.Value) error { + return decodeListArray(s, val, etypeinfo.decoder) + } + case tag.tail: + // A slice with "tail" tag can occur as the last field + // of a struct and is supposed to swallow all remaining + // list elements. The struct decoder already called s.List, + // proceed directly to decoding the elements. + dec = func(s *Stream, val reflect.Value) error { + return decodeSliceElems(s, val, etypeinfo.decoder) + } + default: + dec = func(s *Stream, val reflect.Value) error { + return decodeListSlice(s, val, etypeinfo.decoder) + } + } + return dec, nil +} + +func decodeListSlice(s *Stream, val reflect.Value, elemdec decoder) error { + size, err := s.List() + if err != nil { + return wrapStreamError(err, val.Type()) + } + if size == 0 { + val.Set(reflect.MakeSlice(val.Type(), 0, 0)) + return s.ListEnd() + } + if err := decodeSliceElems(s, val, elemdec); err != nil { + return err + } + return s.ListEnd() +} + +func decodeSliceElems(s *Stream, val reflect.Value, elemdec decoder) error { + i := 0 + for ; ; i++ { + // grow slice if necessary + if i >= val.Cap() { + newcap := val.Cap() + val.Cap()/2 + if newcap < 4 { + newcap = 4 + } + newv := reflect.MakeSlice(val.Type(), val.Len(), newcap) + reflect.Copy(newv, val) + val.Set(newv) + } + if i >= val.Len() { + val.SetLen(i + 1) + } + // decode into element + if err := elemdec(s, val.Index(i)); err == EOL { + break + } else if err != nil { + return addErrorContext(err, fmt.Sprint("[", i, "]")) + } + } + if i < val.Len() { + val.SetLen(i) + } + return nil +} + +func decodeListArray(s *Stream, val reflect.Value, elemdec decoder) error { + if _, err := s.List(); err != nil { + return wrapStreamError(err, val.Type()) + } + vlen := val.Len() + i := 0 + for ; i < vlen; i++ { + if err := elemdec(s, val.Index(i)); err == EOL { + break + } else if err != nil { + return addErrorContext(err, fmt.Sprint("[", i, "]")) + } + } + if i < vlen { + return &decodeError{msg: "input list has too few elements", typ: val.Type()} + } + return wrapStreamError(s.ListEnd(), val.Type()) +} + +func decodeByteSlice(s *Stream, val reflect.Value) error { + b, err := s.Bytes() + if err != nil { + return wrapStreamError(err, val.Type()) + } + val.SetBytes(b) + return nil +} + +func decodeByteArray(s *Stream, val reflect.Value) error { + kind, size, err := s.Kind() + if err != nil { + return err + } + vlen := val.Len() + switch kind { + case Byte: + if vlen == 0 { + return &decodeError{msg: "input string too long", typ: val.Type()} + } + if vlen > 1 { + return &decodeError{msg: "input string too short", typ: val.Type()} + } + bv, _ := s.Uint() + val.Index(0).SetUint(bv) + case String: + if uint64(vlen) < size { + return &decodeError{msg: "input string too long", typ: val.Type()} + } + if uint64(vlen) > size { + return &decodeError{msg: "input string too short", typ: val.Type()} + } + slice := val.Slice(0, vlen).Interface().([]byte) + if err := s.readFull(slice); err != nil { + return err + } + // Reject cases where single byte encoding should have been used. + if size == 1 && slice[0] < 128 { + return wrapStreamError(ErrCanonSize, val.Type()) + } + case List: + return wrapStreamError(ErrExpectedString, val.Type()) + } + return nil +} + +func makeStructDecoder(typ reflect.Type) (decoder, error) { + fields, err := structFields(typ) + if err != nil { + return nil, err + } + dec := func(s *Stream, val reflect.Value) (err error) { + if _, err := s.List(); err != nil { + return wrapStreamError(err, typ) + } + for _, f := range fields { + err := f.info.decoder(s, val.Field(f.index)) + if err == EOL { + return &decodeError{msg: "too few elements", typ: typ} + } else if err != nil { + return addErrorContext(err, "."+typ.Field(f.index).Name) + } + } + return wrapStreamError(s.ListEnd(), typ) + } + return dec, nil +} + +// makePtrDecoder creates a decoder that decodes into +// the pointer's element type. +func makePtrDecoder(typ reflect.Type) (decoder, error) { + etype := typ.Elem() + etypeinfo, err := cachedTypeInfo1(etype, tags{}) + if err != nil { + return nil, err + } + dec := func(s *Stream, val reflect.Value) (err error) { + newval := val + if val.IsNil() { + newval = reflect.New(etype) + } + if err = etypeinfo.decoder(s, newval.Elem()); err == nil { + val.Set(newval) + } + return err + } + return dec, nil +} + +// makeOptionalPtrDecoder creates a decoder that decodes empty values +// as nil. Non-empty values are decoded into a value of the element type, +// just like makePtrDecoder does. +// +// This decoder is used for pointer-typed struct fields with struct tag "nil". +func makeOptionalPtrDecoder(typ reflect.Type) (decoder, error) { + etype := typ.Elem() + etypeinfo, err := cachedTypeInfo1(etype, tags{}) + if err != nil { + return nil, err + } + dec := func(s *Stream, val reflect.Value) (err error) { + kind, size, err := s.Kind() + if err != nil || size == 0 && kind != Byte { + // rearm s.Kind. This is important because the input + // position must advance to the next value even though + // we don't read anything. + s.kind = -1 + // set the pointer to nil. + val.Set(reflect.Zero(typ)) + return err + } + newval := val + if val.IsNil() { + newval = reflect.New(etype) + } + if err = etypeinfo.decoder(s, newval.Elem()); err == nil { + val.Set(newval) + } + return err + } + return dec, nil +} + +var ifsliceType = reflect.TypeOf([]interface{}{}) + +func decodeInterface(s *Stream, val reflect.Value) error { + if val.Type().NumMethod() != 0 { + return fmt.Errorf("rlp: type %v is not RLP-serializable", val.Type()) + } + kind, _, err := s.Kind() + if err != nil { + return err + } + if kind == List { + slice := reflect.New(ifsliceType).Elem() + if err := decodeListSlice(s, slice, decodeInterface); err != nil { + return err + } + val.Set(slice) + } else { + b, err := s.Bytes() + if err != nil { + return err + } + val.Set(reflect.ValueOf(b)) + } + return nil +} + +// This decoder is used for non-pointer values of types +// that implement the Decoder interface using a pointer receiver. +func decodeDecoderNoPtr(s *Stream, val reflect.Value) error { + return val.Addr().Interface().(Decoder).DecodeRLP(s) +} + +func decodeDecoder(s *Stream, val reflect.Value) error { + // Decoder instances are not handled using the pointer rule if the type + // implements Decoder with pointer receiver (i.e. always) + // because it might handle empty values specially. + // We need to allocate one here in this case, like makePtrDecoder does. + if val.Kind() == reflect.Ptr && val.IsNil() { + val.Set(reflect.New(val.Type().Elem())) + } + return val.Interface().(Decoder).DecodeRLP(s) +} + +// Kind represents the kind of value contained in an RLP stream. +type Kind int + +const ( + Byte Kind = iota + String + List +) + +func (k Kind) String() string { + switch k { + case Byte: + return "Byte" + case String: + return "String" + case List: + return "List" + default: + return fmt.Sprintf("Unknown(%d)", k) + } +} + +var ( + // EOL is returned when the end of the current list + // has been reached during streaming. + EOL = errors.New("rlp: end of list") + + // Actual Errors + ErrExpectedString = errors.New("rlp: expected String or Byte") + ErrExpectedList = errors.New("rlp: expected List") + ErrCanonInt = errors.New("rlp: non-canonical integer format") + ErrCanonSize = errors.New("rlp: non-canonical size information") + ErrElemTooLarge = errors.New("rlp: element is larger than containing list") + ErrValueTooLarge = errors.New("rlp: value size exceeds available input length") + + // This error is reported by DecodeBytes if the slice contains + // additional data after the first RLP value. + ErrMoreThanOneValue = errors.New("rlp: input contains more than one value") + + // internal errors + errNotInList = errors.New("rlp: call of ListEnd outside of any list") + errNotAtEOL = errors.New("rlp: call of ListEnd not positioned at EOL") + errUintOverflow = errors.New("rlp: uint overflow") +) + +// ByteReader must be implemented by any input reader for a Stream. It +// is implemented by e.g. bufio.Reader and bytes.Reader. +type ByteReader interface { + io.Reader + io.ByteReader +} + +// Stream can be used for piecemeal decoding of an input stream. This +// is useful if the input is very large or if the decoding rules for a +// type depend on the input structure. Stream does not keep an +// internal buffer. After decoding a value, the input reader will be +// positioned just before the type information for the next value. +// +// When decoding a list and the input position reaches the declared +// length of the list, all operations will return error EOL. +// The end of the list must be acknowledged using ListEnd to continue +// reading the enclosing list. +// +// Stream is not safe for concurrent use. +type Stream struct { + r ByteReader + + // number of bytes remaining to be read from r. + remaining uint64 + limited bool + + // auxiliary buffer for integer decoding + uintbuf []byte + + kind Kind // kind of value ahead + size uint64 // size of value ahead + byteval byte // value of single byte in type tag + kinderr error // error from last readKind + stack []listpos +} + +type listpos struct{ pos, size uint64 } + +// NewStream creates a new decoding stream reading from r. +// +// If r implements the ByteReader interface, Stream will +// not introduce any buffering. +// +// For non-toplevel values, Stream returns ErrElemTooLarge +// for values that do not fit into the enclosing list. +// +// Stream supports an optional input limit. If a limit is set, the +// size of any toplevel value will be checked against the remaining +// input length. Stream operations that encounter a value exceeding +// the remaining input length will return ErrValueTooLarge. The limit +// can be set by passing a non-zero value for inputLimit. +// +// If r is a bytes.Reader or strings.Reader, the input limit is set to +// the length of r's underlying data unless an explicit limit is +// provided. +func NewStream(r io.Reader, inputLimit uint64) *Stream { + s := new(Stream) + s.Reset(r, inputLimit) + return s +} + +// NewListStream creates a new stream that pretends to be positioned +// at an encoded list of the given length. +func NewListStream(r io.Reader, len uint64) *Stream { + s := new(Stream) + s.Reset(r, len) + s.kind = List + s.size = len + return s +} + +// Bytes reads an RLP string and returns its contents as a byte slice. +// If the input does not contain an RLP string, the returned +// error will be ErrExpectedString. +func (s *Stream) Bytes() ([]byte, error) { + kind, size, err := s.Kind() + if err != nil { + return nil, err + } + switch kind { + case Byte: + s.kind = -1 // rearm Kind + return []byte{s.byteval}, nil + case String: + b := make([]byte, size) + if err = s.readFull(b); err != nil { + return nil, err + } + if size == 1 && b[0] < 128 { + return nil, ErrCanonSize + } + return b, nil + default: + return nil, ErrExpectedString + } +} + +// Raw reads a raw encoded value including RLP type information. +func (s *Stream) Raw() ([]byte, error) { + kind, size, err := s.Kind() + if err != nil { + return nil, err + } + if kind == Byte { + s.kind = -1 // rearm Kind + return []byte{s.byteval}, nil + } + // the original header has already been read and is no longer + // available. read content and put a new header in front of it. + start := headsize(size) + buf := make([]byte, uint64(start)+size) + if err := s.readFull(buf[start:]); err != nil { + return nil, err + } + if kind == String { + puthead(buf, 0x80, 0xB8, size) + } else { + puthead(buf, 0xC0, 0xF7, size) + } + return buf, nil +} + +// Uint reads an RLP string of up to 8 bytes and returns its contents +// as an unsigned integer. If the input does not contain an RLP string, the +// returned error will be ErrExpectedString. +func (s *Stream) Uint() (uint64, error) { + return s.uint(64) +} + +func (s *Stream) uint(maxbits int) (uint64, error) { + kind, size, err := s.Kind() + if err != nil { + return 0, err + } + switch kind { + case Byte: + if s.byteval == 0 { + return 0, ErrCanonInt + } + s.kind = -1 // rearm Kind + return uint64(s.byteval), nil + case String: + if size > uint64(maxbits/8) { + return 0, errUintOverflow + } + v, err := s.readUint(byte(size)) + switch { + case err == ErrCanonSize: + // Adjust error because we're not reading a size right now. + return 0, ErrCanonInt + case err != nil: + return 0, err + case size > 0 && v < 128: + return 0, ErrCanonSize + default: + return v, nil + } + default: + return 0, ErrExpectedString + } +} + +// Bool reads an RLP string of up to 1 byte and returns its contents +// as a boolean. If the input does not contain an RLP string, the +// returned error will be ErrExpectedString. +func (s *Stream) Bool() (bool, error) { + num, err := s.uint(8) + if err != nil { + return false, err + } + switch num { + case 0: + return false, nil + case 1: + return true, nil + default: + return false, fmt.Errorf("rlp: invalid boolean value: %d", num) + } +} + +// List starts decoding an RLP list. If the input does not contain a +// list, the returned error will be ErrExpectedList. When the list's +// end has been reached, any Stream operation will return EOL. +func (s *Stream) List() (size uint64, err error) { + kind, size, err := s.Kind() + if err != nil { + return 0, err + } + if kind != List { + return 0, ErrExpectedList + } + s.stack = append(s.stack, listpos{0, size}) + s.kind = -1 + s.size = 0 + return size, nil +} + +// ListEnd returns to the enclosing list. +// The input reader must be positioned at the end of a list. +func (s *Stream) ListEnd() error { + if len(s.stack) == 0 { + return errNotInList + } + tos := s.stack[len(s.stack)-1] + if tos.pos != tos.size { + return errNotAtEOL + } + s.stack = s.stack[:len(s.stack)-1] // pop + if len(s.stack) > 0 { + s.stack[len(s.stack)-1].pos += tos.size + } + s.kind = -1 + s.size = 0 + return nil +} + +// Decode decodes a value and stores the result in the value pointed +// to by val. Please see the documentation for the Decode function +// to learn about the decoding rules. +func (s *Stream) Decode(val interface{}) error { + if val == nil { + return errDecodeIntoNil + } + rval := reflect.ValueOf(val) + rtyp := rval.Type() + if rtyp.Kind() != reflect.Ptr { + return errNoPointer + } + if rval.IsNil() { + return errDecodeIntoNil + } + info, err := cachedTypeInfo(rtyp.Elem(), tags{}) + if err != nil { + return err + } + + err = info.decoder(s, rval.Elem()) + if decErr, ok := err.(*decodeError); ok && len(decErr.ctx) > 0 { + // add decode target type to error so context has more meaning + decErr.ctx = append(decErr.ctx, fmt.Sprint("(", rtyp.Elem(), ")")) + } + return err +} + +// Reset discards any information about the current decoding context +// and starts reading from r. This method is meant to facilitate reuse +// of a preallocated Stream across many decoding operations. +// +// If r does not also implement ByteReader, Stream will do its own +// buffering. +func (s *Stream) Reset(r io.Reader, inputLimit uint64) { + if inputLimit > 0 { + s.remaining = inputLimit + s.limited = true + } else { + // Attempt to automatically discover + // the limit when reading from a byte slice. + switch br := r.(type) { + case *bytes.Reader: + s.remaining = uint64(br.Len()) + s.limited = true + case *strings.Reader: + s.remaining = uint64(br.Len()) + s.limited = true + default: + s.limited = false + } + } + // Wrap r with a buffer if it doesn't have one. + bufr, ok := r.(ByteReader) + if !ok { + bufr = bufio.NewReader(r) + } + s.r = bufr + // Reset the decoding context. + s.stack = s.stack[:0] + s.size = 0 + s.kind = -1 + s.kinderr = nil + if s.uintbuf == nil { + s.uintbuf = make([]byte, 8) + } +} + +// Kind returns the kind and size of the next value in the +// input stream. +// +// The returned size is the number of bytes that make up the value. +// For kind == Byte, the size is zero because the value is +// contained in the type tag. +// +// The first call to Kind will read size information from the input +// reader and leave it positioned at the start of the actual bytes of +// the value. Subsequent calls to Kind (until the value is decoded) +// will not advance the input reader and return cached information. +func (s *Stream) Kind() (kind Kind, size uint64, err error) { + var tos *listpos + if len(s.stack) > 0 { + tos = &s.stack[len(s.stack)-1] + } + if s.kind < 0 { + s.kinderr = nil + // Don't read further if we're at the end of the + // innermost list. + if tos != nil && tos.pos == tos.size { + return 0, 0, EOL + } + s.kind, s.size, s.kinderr = s.readKind() + if s.kinderr == nil { + if tos == nil { + // At toplevel, check that the value is smaller + // than the remaining input length. + if s.limited && s.size > s.remaining { + s.kinderr = ErrValueTooLarge + } + } else { + // Inside a list, check that the value doesn't overflow the list. + if s.size > tos.size-tos.pos { + s.kinderr = ErrElemTooLarge + } + } + } + } + // Note: this might return a sticky error generated + // by an earlier call to readKind. + return s.kind, s.size, s.kinderr +} + +func (s *Stream) readKind() (kind Kind, size uint64, err error) { + b, err := s.readByte() + if err != nil { + if len(s.stack) == 0 { + // At toplevel, Adjust the error to actual EOF. io.EOF is + // used by callers to determine when to stop decoding. + switch err { + case io.ErrUnexpectedEOF: + err = io.EOF + case ErrValueTooLarge: + err = io.EOF + } + } + return 0, 0, err + } + s.byteval = 0 + switch { + case b < 0x80: + // For a single byte whose value is in the [0x00, 0x7F] range, that byte + // is its own RLP encoding. + s.byteval = b + return Byte, 0, nil + case b < 0xB8: + // Otherwise, if a string is 0-55 bytes long, + // the RLP encoding consists of a single byte with value 0x80 plus the + // length of the string followed by the string. The range of the first + // byte is thus [0x80, 0xB7]. + return String, uint64(b - 0x80), nil + case b < 0xC0: + // If a string is more than 55 bytes long, the + // RLP encoding consists of a single byte with value 0xB7 plus the length + // of the length of the string in binary form, followed by the length of + // the string, followed by the string. For example, a length-1024 string + // would be encoded as 0xB90400 followed by the string. The range of + // the first byte is thus [0xB8, 0xBF]. + size, err = s.readUint(b - 0xB7) + if err == nil && size < 56 { + err = ErrCanonSize + } + return String, size, err + case b < 0xF8: + // If the total payload of a list + // (i.e. the combined length of all its items) is 0-55 bytes long, the + // RLP encoding consists of a single byte with value 0xC0 plus the length + // of the list followed by the concatenation of the RLP encodings of the + // items. The range of the first byte is thus [0xC0, 0xF7]. + return List, uint64(b - 0xC0), nil + default: + // If the total payload of a list is more than 55 bytes long, + // the RLP encoding consists of a single byte with value 0xF7 + // plus the length of the length of the payload in binary + // form, followed by the length of the payload, followed by + // the concatenation of the RLP encodings of the items. The + // range of the first byte is thus [0xF8, 0xFF]. + size, err = s.readUint(b - 0xF7) + if err == nil && size < 56 { + err = ErrCanonSize + } + return List, size, err + } +} + +func (s *Stream) readUint(size byte) (uint64, error) { + switch size { + case 0: + s.kind = -1 // rearm Kind + return 0, nil + case 1: + b, err := s.readByte() + return uint64(b), err + default: + start := int(8 - size) + for i := 0; i < start; i++ { + s.uintbuf[i] = 0 + } + if err := s.readFull(s.uintbuf[start:]); err != nil { + return 0, err + } + if s.uintbuf[start] == 0 { + // Note: readUint is also used to decode integer + // values. The error needs to be adjusted to become + // ErrCanonInt in this case. + return 0, ErrCanonSize + } + return binary.BigEndian.Uint64(s.uintbuf), nil + } +} + +func (s *Stream) readFull(buf []byte) (err error) { + if err := s.willRead(uint64(len(buf))); err != nil { + return err + } + var nn, n int + for n < len(buf) && err == nil { + nn, err = s.r.Read(buf[n:]) + n += nn + } + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return err +} + +func (s *Stream) readByte() (byte, error) { + if err := s.willRead(1); err != nil { + return 0, err + } + b, err := s.r.ReadByte() + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return b, err +} + +func (s *Stream) willRead(n uint64) error { + s.kind = -1 // rearm Kind + + if len(s.stack) > 0 { + // check list overflow + tos := s.stack[len(s.stack)-1] + if n > tos.size-tos.pos { + return ErrElemTooLarge + } + s.stack[len(s.stack)-1].pos += n + } + if s.limited { + if n > s.remaining { + return ErrValueTooLarge + } + s.remaining -= n + } + return nil +} diff --git a/vendor/github.com/getamis/go-ethereum/rlp/doc.go b/vendor/github.com/getamis/go-ethereum/rlp/doc.go new file mode 100644 index 00000000..b3a81fe2 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/rlp/doc.go @@ -0,0 +1,33 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +/* +Package rlp implements the RLP serialization format. + +The purpose of RLP (Recursive Linear Prefix) is to encode arbitrarily +nested arrays of binary data, and RLP is the main encoding method used +to serialize objects in Ethereum. The only purpose of RLP is to encode +structure; encoding specific atomic data types (eg. strings, ints, +floats) is left up to higher-order protocols; in Ethereum integers +must be represented in big endian binary form with no leading zeroes +(thus making the integer value zero equivalent to the empty byte +array). + +RLP values are distinguished by a type tag. The type tag precedes the +value in the input stream and defines the size and kind of the bytes +that follow. +*/ +package rlp diff --git a/vendor/github.com/getamis/go-ethereum/rlp/encode.go b/vendor/github.com/getamis/go-ethereum/rlp/encode.go new file mode 100644 index 00000000..44592c2f --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/rlp/encode.go @@ -0,0 +1,652 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rlp + +import ( + "fmt" + "io" + "math/big" + "reflect" + "sync" +) + +var ( + // Common encoded values. + // These are useful when implementing EncodeRLP. + EmptyString = []byte{0x80} + EmptyList = []byte{0xC0} +) + +// Encoder is implemented by types that require custom +// encoding rules or want to encode private fields. +type Encoder interface { + // EncodeRLP should write the RLP encoding of its receiver to w. + // If the implementation is a pointer method, it may also be + // called for nil pointers. + // + // Implementations should generate valid RLP. The data written is + // not verified at the moment, but a future version might. It is + // recommended to write only a single value but writing multiple + // values or no value at all is also permitted. + EncodeRLP(io.Writer) error +} + +// Encode writes the RLP encoding of val to w. Note that Encode may +// perform many small writes in some cases. Consider making w +// buffered. +// +// Encode uses the following type-dependent encoding rules: +// +// If the type implements the Encoder interface, Encode calls +// EncodeRLP. This is true even for nil pointers, please see the +// documentation for Encoder. +// +// To encode a pointer, the value being pointed to is encoded. For nil +// pointers, Encode will encode the zero value of the type. A nil +// pointer to a struct type always encodes as an empty RLP list. +// A nil pointer to an array encodes as an empty list (or empty string +// if the array has element type byte). +// +// Struct values are encoded as an RLP list of all their encoded +// public fields. Recursive struct types are supported. +// +// To encode slices and arrays, the elements are encoded as an RLP +// list of the value's elements. Note that arrays and slices with +// element type uint8 or byte are always encoded as an RLP string. +// +// A Go string is encoded as an RLP string. +// +// An unsigned integer value is encoded as an RLP string. Zero always +// encodes as an empty RLP string. Encode also supports *big.Int. +// +// An interface value encodes as the value contained in the interface. +// +// Boolean values are not supported, nor are signed integers, floating +// point numbers, maps, channels and functions. +func Encode(w io.Writer, val interface{}) error { + if outer, ok := w.(*encbuf); ok { + // Encode was called by some type's EncodeRLP. + // Avoid copying by writing to the outer encbuf directly. + return outer.encode(val) + } + eb := encbufPool.Get().(*encbuf) + defer encbufPool.Put(eb) + eb.reset() + if err := eb.encode(val); err != nil { + return err + } + return eb.toWriter(w) +} + +// EncodeBytes returns the RLP encoding of val. +// Please see the documentation of Encode for the encoding rules. +func EncodeToBytes(val interface{}) ([]byte, error) { + eb := encbufPool.Get().(*encbuf) + defer encbufPool.Put(eb) + eb.reset() + if err := eb.encode(val); err != nil { + return nil, err + } + return eb.toBytes(), nil +} + +// EncodeReader returns a reader from which the RLP encoding of val +// can be read. The returned size is the total size of the encoded +// data. +// +// Please see the documentation of Encode for the encoding rules. +func EncodeToReader(val interface{}) (size int, r io.Reader, err error) { + eb := encbufPool.Get().(*encbuf) + eb.reset() + if err := eb.encode(val); err != nil { + return 0, nil, err + } + return eb.size(), &encReader{buf: eb}, nil +} + +type encbuf struct { + str []byte // string data, contains everything except list headers + lheads []*listhead // all list headers + lhsize int // sum of sizes of all encoded list headers + sizebuf []byte // 9-byte auxiliary buffer for uint encoding +} + +type listhead struct { + offset int // index of this header in string data + size int // total size of encoded data (including list headers) +} + +// encode writes head to the given buffer, which must be at least +// 9 bytes long. It returns the encoded bytes. +func (head *listhead) encode(buf []byte) []byte { + return buf[:puthead(buf, 0xC0, 0xF7, uint64(head.size))] +} + +// headsize returns the size of a list or string header +// for a value of the given size. +func headsize(size uint64) int { + if size < 56 { + return 1 + } + return 1 + intsize(size) +} + +// puthead writes a list or string header to buf. +// buf must be at least 9 bytes long. +func puthead(buf []byte, smalltag, largetag byte, size uint64) int { + if size < 56 { + buf[0] = smalltag + byte(size) + return 1 + } else { + sizesize := putint(buf[1:], size) + buf[0] = largetag + byte(sizesize) + return sizesize + 1 + } +} + +// encbufs are pooled. +var encbufPool = sync.Pool{ + New: func() interface{} { return &encbuf{sizebuf: make([]byte, 9)} }, +} + +func (w *encbuf) reset() { + w.lhsize = 0 + if w.str != nil { + w.str = w.str[:0] + } + if w.lheads != nil { + w.lheads = w.lheads[:0] + } +} + +// encbuf implements io.Writer so it can be passed it into EncodeRLP. +func (w *encbuf) Write(b []byte) (int, error) { + w.str = append(w.str, b...) + return len(b), nil +} + +func (w *encbuf) encode(val interface{}) error { + rval := reflect.ValueOf(val) + ti, err := cachedTypeInfo(rval.Type(), tags{}) + if err != nil { + return err + } + return ti.writer(rval, w) +} + +func (w *encbuf) encodeStringHeader(size int) { + if size < 56 { + w.str = append(w.str, 0x80+byte(size)) + } else { + // TODO: encode to w.str directly + sizesize := putint(w.sizebuf[1:], uint64(size)) + w.sizebuf[0] = 0xB7 + byte(sizesize) + w.str = append(w.str, w.sizebuf[:sizesize+1]...) + } +} + +func (w *encbuf) encodeString(b []byte) { + if len(b) == 1 && b[0] <= 0x7F { + // fits single byte, no string header + w.str = append(w.str, b[0]) + } else { + w.encodeStringHeader(len(b)) + w.str = append(w.str, b...) + } +} + +func (w *encbuf) list() *listhead { + lh := &listhead{offset: len(w.str), size: w.lhsize} + w.lheads = append(w.lheads, lh) + return lh +} + +func (w *encbuf) listEnd(lh *listhead) { + lh.size = w.size() - lh.offset - lh.size + if lh.size < 56 { + w.lhsize += 1 // length encoded into kind tag + } else { + w.lhsize += 1 + intsize(uint64(lh.size)) + } +} + +func (w *encbuf) size() int { + return len(w.str) + w.lhsize +} + +func (w *encbuf) toBytes() []byte { + out := make([]byte, w.size()) + strpos := 0 + pos := 0 + for _, head := range w.lheads { + // write string data before header + n := copy(out[pos:], w.str[strpos:head.offset]) + pos += n + strpos += n + // write the header + enc := head.encode(out[pos:]) + pos += len(enc) + } + // copy string data after the last list header + copy(out[pos:], w.str[strpos:]) + return out +} + +func (w *encbuf) toWriter(out io.Writer) (err error) { + strpos := 0 + for _, head := range w.lheads { + // write string data before header + if head.offset-strpos > 0 { + n, err := out.Write(w.str[strpos:head.offset]) + strpos += n + if err != nil { + return err + } + } + // write the header + enc := head.encode(w.sizebuf) + if _, err = out.Write(enc); err != nil { + return err + } + } + if strpos < len(w.str) { + // write string data after the last list header + _, err = out.Write(w.str[strpos:]) + } + return err +} + +// encReader is the io.Reader returned by EncodeToReader. +// It releases its encbuf at EOF. +type encReader struct { + buf *encbuf // the buffer we're reading from. this is nil when we're at EOF. + lhpos int // index of list header that we're reading + strpos int // current position in string buffer + piece []byte // next piece to be read +} + +func (r *encReader) Read(b []byte) (n int, err error) { + for { + if r.piece = r.next(); r.piece == nil { + // Put the encode buffer back into the pool at EOF when it + // is first encountered. Subsequent calls still return EOF + // as the error but the buffer is no longer valid. + if r.buf != nil { + encbufPool.Put(r.buf) + r.buf = nil + } + return n, io.EOF + } + nn := copy(b[n:], r.piece) + n += nn + if nn < len(r.piece) { + // piece didn't fit, see you next time. + r.piece = r.piece[nn:] + return n, nil + } + r.piece = nil + } +} + +// next returns the next piece of data to be read. +// it returns nil at EOF. +func (r *encReader) next() []byte { + switch { + case r.buf == nil: + return nil + + case r.piece != nil: + // There is still data available for reading. + return r.piece + + case r.lhpos < len(r.buf.lheads): + // We're before the last list header. + head := r.buf.lheads[r.lhpos] + sizebefore := head.offset - r.strpos + if sizebefore > 0 { + // String data before header. + p := r.buf.str[r.strpos:head.offset] + r.strpos += sizebefore + return p + } else { + r.lhpos++ + return head.encode(r.buf.sizebuf) + } + + case r.strpos < len(r.buf.str): + // String data at the end, after all list headers. + p := r.buf.str[r.strpos:] + r.strpos = len(r.buf.str) + return p + + default: + return nil + } +} + +var ( + encoderInterface = reflect.TypeOf(new(Encoder)).Elem() + big0 = big.NewInt(0) +) + +// makeWriter creates a writer function for the given type. +func makeWriter(typ reflect.Type, ts tags) (writer, error) { + kind := typ.Kind() + switch { + case typ == rawValueType: + return writeRawValue, nil + case typ.Implements(encoderInterface): + return writeEncoder, nil + case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface): + return writeEncoderNoPtr, nil + case kind == reflect.Interface: + return writeInterface, nil + case typ.AssignableTo(reflect.PtrTo(bigInt)): + return writeBigIntPtr, nil + case typ.AssignableTo(bigInt): + return writeBigIntNoPtr, nil + case isUint(kind): + return writeUint, nil + case kind == reflect.Bool: + return writeBool, nil + case kind == reflect.String: + return writeString, nil + case kind == reflect.Slice && isByte(typ.Elem()): + return writeBytes, nil + case kind == reflect.Array && isByte(typ.Elem()): + return writeByteArray, nil + case kind == reflect.Slice || kind == reflect.Array: + return makeSliceWriter(typ, ts) + case kind == reflect.Struct: + return makeStructWriter(typ) + case kind == reflect.Ptr: + return makePtrWriter(typ) + default: + return nil, fmt.Errorf("rlp: type %v is not RLP-serializable", typ) + } +} + +func isByte(typ reflect.Type) bool { + return typ.Kind() == reflect.Uint8 && !typ.Implements(encoderInterface) +} + +func writeRawValue(val reflect.Value, w *encbuf) error { + w.str = append(w.str, val.Bytes()...) + return nil +} + +func writeUint(val reflect.Value, w *encbuf) error { + i := val.Uint() + if i == 0 { + w.str = append(w.str, 0x80) + } else if i < 128 { + // fits single byte + w.str = append(w.str, byte(i)) + } else { + // TODO: encode int to w.str directly + s := putint(w.sizebuf[1:], i) + w.sizebuf[0] = 0x80 + byte(s) + w.str = append(w.str, w.sizebuf[:s+1]...) + } + return nil +} + +func writeBool(val reflect.Value, w *encbuf) error { + if val.Bool() { + w.str = append(w.str, 0x01) + } else { + w.str = append(w.str, 0x80) + } + return nil +} + +func writeBigIntPtr(val reflect.Value, w *encbuf) error { + ptr := val.Interface().(*big.Int) + if ptr == nil { + w.str = append(w.str, 0x80) + return nil + } + return writeBigInt(ptr, w) +} + +func writeBigIntNoPtr(val reflect.Value, w *encbuf) error { + i := val.Interface().(big.Int) + return writeBigInt(&i, w) +} + +func writeBigInt(i *big.Int, w *encbuf) error { + if cmp := i.Cmp(big0); cmp == -1 { + return fmt.Errorf("rlp: cannot encode negative *big.Int") + } else if cmp == 0 { + w.str = append(w.str, 0x80) + } else { + w.encodeString(i.Bytes()) + } + return nil +} + +func writeBytes(val reflect.Value, w *encbuf) error { + w.encodeString(val.Bytes()) + return nil +} + +func writeByteArray(val reflect.Value, w *encbuf) error { + if !val.CanAddr() { + // Slice requires the value to be addressable. + // Make it addressable by copying. + copy := reflect.New(val.Type()).Elem() + copy.Set(val) + val = copy + } + size := val.Len() + slice := val.Slice(0, size).Bytes() + w.encodeString(slice) + return nil +} + +func writeString(val reflect.Value, w *encbuf) error { + s := val.String() + if len(s) == 1 && s[0] <= 0x7f { + // fits single byte, no string header + w.str = append(w.str, s[0]) + } else { + w.encodeStringHeader(len(s)) + w.str = append(w.str, s...) + } + return nil +} + +func writeEncoder(val reflect.Value, w *encbuf) error { + return val.Interface().(Encoder).EncodeRLP(w) +} + +// writeEncoderNoPtr handles non-pointer values that implement Encoder +// with a pointer receiver. +func writeEncoderNoPtr(val reflect.Value, w *encbuf) error { + if !val.CanAddr() { + // We can't get the address. It would be possible to make the + // value addressable by creating a shallow copy, but this + // creates other problems so we're not doing it (yet). + // + // package json simply doesn't call MarshalJSON for cases like + // this, but encodes the value as if it didn't implement the + // interface. We don't want to handle it that way. + return fmt.Errorf("rlp: game over: unadressable value of type %v, EncodeRLP is pointer method", val.Type()) + } + return val.Addr().Interface().(Encoder).EncodeRLP(w) +} + +func writeInterface(val reflect.Value, w *encbuf) error { + if val.IsNil() { + // Write empty list. This is consistent with the previous RLP + // encoder that we had and should therefore avoid any + // problems. + w.str = append(w.str, 0xC0) + return nil + } + eval := val.Elem() + ti, err := cachedTypeInfo(eval.Type(), tags{}) + if err != nil { + return err + } + return ti.writer(eval, w) +} + +func makeSliceWriter(typ reflect.Type, ts tags) (writer, error) { + etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{}) + if err != nil { + return nil, err + } + writer := func(val reflect.Value, w *encbuf) error { + if !ts.tail { + defer w.listEnd(w.list()) + } + vlen := val.Len() + for i := 0; i < vlen; i++ { + if err := etypeinfo.writer(val.Index(i), w); err != nil { + return err + } + } + return nil + } + return writer, nil +} + +func makeStructWriter(typ reflect.Type) (writer, error) { + fields, err := structFields(typ) + if err != nil { + return nil, err + } + writer := func(val reflect.Value, w *encbuf) error { + lh := w.list() + for _, f := range fields { + if err := f.info.writer(val.Field(f.index), w); err != nil { + return err + } + } + w.listEnd(lh) + return nil + } + return writer, nil +} + +func makePtrWriter(typ reflect.Type) (writer, error) { + etypeinfo, err := cachedTypeInfo1(typ.Elem(), tags{}) + if err != nil { + return nil, err + } + + // determine nil pointer handler + var nilfunc func(*encbuf) error + kind := typ.Elem().Kind() + switch { + case kind == reflect.Array && isByte(typ.Elem().Elem()): + nilfunc = func(w *encbuf) error { + w.str = append(w.str, 0x80) + return nil + } + case kind == reflect.Struct || kind == reflect.Array: + nilfunc = func(w *encbuf) error { + // encoding the zero value of a struct/array could trigger + // infinite recursion, avoid that. + w.listEnd(w.list()) + return nil + } + default: + zero := reflect.Zero(typ.Elem()) + nilfunc = func(w *encbuf) error { + return etypeinfo.writer(zero, w) + } + } + + writer := func(val reflect.Value, w *encbuf) error { + if val.IsNil() { + return nilfunc(w) + } else { + return etypeinfo.writer(val.Elem(), w) + } + } + return writer, err +} + +// putint writes i to the beginning of b in big endian byte +// order, using the least number of bytes needed to represent i. +func putint(b []byte, i uint64) (size int) { + switch { + case i < (1 << 8): + b[0] = byte(i) + return 1 + case i < (1 << 16): + b[0] = byte(i >> 8) + b[1] = byte(i) + return 2 + case i < (1 << 24): + b[0] = byte(i >> 16) + b[1] = byte(i >> 8) + b[2] = byte(i) + return 3 + case i < (1 << 32): + b[0] = byte(i >> 24) + b[1] = byte(i >> 16) + b[2] = byte(i >> 8) + b[3] = byte(i) + return 4 + case i < (1 << 40): + b[0] = byte(i >> 32) + b[1] = byte(i >> 24) + b[2] = byte(i >> 16) + b[3] = byte(i >> 8) + b[4] = byte(i) + return 5 + case i < (1 << 48): + b[0] = byte(i >> 40) + b[1] = byte(i >> 32) + b[2] = byte(i >> 24) + b[3] = byte(i >> 16) + b[4] = byte(i >> 8) + b[5] = byte(i) + return 6 + case i < (1 << 56): + b[0] = byte(i >> 48) + b[1] = byte(i >> 40) + b[2] = byte(i >> 32) + b[3] = byte(i >> 24) + b[4] = byte(i >> 16) + b[5] = byte(i >> 8) + b[6] = byte(i) + return 7 + default: + b[0] = byte(i >> 56) + b[1] = byte(i >> 48) + b[2] = byte(i >> 40) + b[3] = byte(i >> 32) + b[4] = byte(i >> 24) + b[5] = byte(i >> 16) + b[6] = byte(i >> 8) + b[7] = byte(i) + return 8 + } +} + +// intsize computes the minimum number of bytes required to store i. +func intsize(i uint64) (size int) { + for size = 1; ; size++ { + if i >>= 8; i == 0 { + return size + } + } +} diff --git a/vendor/github.com/getamis/go-ethereum/rlp/raw.go b/vendor/github.com/getamis/go-ethereum/rlp/raw.go new file mode 100644 index 00000000..6bf1c1df --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/rlp/raw.go @@ -0,0 +1,156 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rlp + +import ( + "io" + "reflect" +) + +// RawValue represents an encoded RLP value and can be used to delay +// RLP decoding or to precompute an encoding. Note that the decoder does +// not verify whether the content of RawValues is valid RLP. +type RawValue []byte + +var rawValueType = reflect.TypeOf(RawValue{}) + +// ListSize returns the encoded size of an RLP list with the given +// content size. +func ListSize(contentSize uint64) uint64 { + return uint64(headsize(contentSize)) + contentSize +} + +// Split returns the content of first RLP value and any +// bytes after the value as subslices of b. +func Split(b []byte) (k Kind, content, rest []byte, err error) { + k, ts, cs, err := readKind(b) + if err != nil { + return 0, nil, b, err + } + return k, b[ts : ts+cs], b[ts+cs:], nil +} + +// SplitString splits b into the content of an RLP string +// and any remaining bytes after the string. +func SplitString(b []byte) (content, rest []byte, err error) { + k, content, rest, err := Split(b) + if err != nil { + return nil, b, err + } + if k == List { + return nil, b, ErrExpectedString + } + return content, rest, nil +} + +// SplitList splits b into the content of a list and any remaining +// bytes after the list. +func SplitList(b []byte) (content, rest []byte, err error) { + k, content, rest, err := Split(b) + if err != nil { + return nil, b, err + } + if k != List { + return nil, b, ErrExpectedList + } + return content, rest, nil +} + +// CountValues counts the number of encoded values in b. +func CountValues(b []byte) (int, error) { + i := 0 + for ; len(b) > 0; i++ { + _, tagsize, size, err := readKind(b) + if err != nil { + return 0, err + } + b = b[tagsize+size:] + } + return i, nil +} + +func readKind(buf []byte) (k Kind, tagsize, contentsize uint64, err error) { + if len(buf) == 0 { + return 0, 0, 0, io.ErrUnexpectedEOF + } + b := buf[0] + switch { + case b < 0x80: + k = Byte + tagsize = 0 + contentsize = 1 + case b < 0xB8: + k = String + tagsize = 1 + contentsize = uint64(b - 0x80) + // Reject strings that should've been single bytes. + if contentsize == 1 && buf[1] < 128 { + return 0, 0, 0, ErrCanonSize + } + case b < 0xC0: + k = String + tagsize = uint64(b-0xB7) + 1 + contentsize, err = readSize(buf[1:], b-0xB7) + case b < 0xF8: + k = List + tagsize = 1 + contentsize = uint64(b - 0xC0) + default: + k = List + tagsize = uint64(b-0xF7) + 1 + contentsize, err = readSize(buf[1:], b-0xF7) + } + if err != nil { + return 0, 0, 0, err + } + // Reject values larger than the input slice. + if contentsize > uint64(len(buf))-tagsize { + return 0, 0, 0, ErrValueTooLarge + } + return k, tagsize, contentsize, err +} + +func readSize(b []byte, slen byte) (uint64, error) { + if int(slen) > len(b) { + return 0, io.ErrUnexpectedEOF + } + var s uint64 + switch slen { + case 1: + s = uint64(b[0]) + case 2: + s = uint64(b[0])<<8 | uint64(b[1]) + case 3: + s = uint64(b[0])<<16 | uint64(b[1])<<8 | uint64(b[2]) + case 4: + s = uint64(b[0])<<24 | uint64(b[1])<<16 | uint64(b[2])<<8 | uint64(b[3]) + case 5: + s = uint64(b[0])<<32 | uint64(b[1])<<24 | uint64(b[2])<<16 | uint64(b[3])<<8 | uint64(b[4]) + case 6: + s = uint64(b[0])<<40 | uint64(b[1])<<32 | uint64(b[2])<<24 | uint64(b[3])<<16 | uint64(b[4])<<8 | uint64(b[5]) + case 7: + s = uint64(b[0])<<48 | uint64(b[1])<<40 | uint64(b[2])<<32 | uint64(b[3])<<24 | uint64(b[4])<<16 | uint64(b[5])<<8 | uint64(b[6]) + case 8: + s = uint64(b[0])<<56 | uint64(b[1])<<48 | uint64(b[2])<<40 | uint64(b[3])<<32 | uint64(b[4])<<24 | uint64(b[5])<<16 | uint64(b[6])<<8 | uint64(b[7]) + } + // Reject sizes < 56 (shouldn't have separate size) and sizes with + // leading zero bytes. + if s < 56 || b[0] == 0 { + return 0, ErrCanonSize + } + return s, nil +} diff --git a/vendor/github.com/getamis/go-ethereum/rlp/typecache.go b/vendor/github.com/getamis/go-ethereum/rlp/typecache.go new file mode 100644 index 00000000..3df799e1 --- /dev/null +++ b/vendor/github.com/getamis/go-ethereum/rlp/typecache.go @@ -0,0 +1,156 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package rlp + +import ( + "fmt" + "reflect" + "strings" + "sync" +) + +var ( + typeCacheMutex sync.RWMutex + typeCache = make(map[typekey]*typeinfo) +) + +type typeinfo struct { + decoder + writer +} + +// represents struct tags +type tags struct { + // rlp:"nil" controls whether empty input results in a nil pointer. + nilOK bool + // rlp:"tail" controls whether this field swallows additional list + // elements. It can only be set for the last field, which must be + // of slice type. + tail bool + // rlp:"-" ignores fields. + ignored bool +} + +type typekey struct { + reflect.Type + // the key must include the struct tags because they + // might generate a different decoder. + tags +} + +type decoder func(*Stream, reflect.Value) error + +type writer func(reflect.Value, *encbuf) error + +func cachedTypeInfo(typ reflect.Type, tags tags) (*typeinfo, error) { + typeCacheMutex.RLock() + info := typeCache[typekey{typ, tags}] + typeCacheMutex.RUnlock() + if info != nil { + return info, nil + } + // not in the cache, need to generate info for this type. + typeCacheMutex.Lock() + defer typeCacheMutex.Unlock() + return cachedTypeInfo1(typ, tags) +} + +func cachedTypeInfo1(typ reflect.Type, tags tags) (*typeinfo, error) { + key := typekey{typ, tags} + info := typeCache[key] + if info != nil { + // another goroutine got the write lock first + return info, nil + } + // put a dummmy value into the cache before generating. + // if the generator tries to lookup itself, it will get + // the dummy value and won't call itself recursively. + typeCache[key] = new(typeinfo) + info, err := genTypeInfo(typ, tags) + if err != nil { + // remove the dummy value if the generator fails + delete(typeCache, key) + return nil, err + } + *typeCache[key] = *info + return typeCache[key], err +} + +type field struct { + index int + info *typeinfo +} + +func structFields(typ reflect.Type) (fields []field, err error) { + for i := 0; i < typ.NumField(); i++ { + if f := typ.Field(i); f.PkgPath == "" { // exported + tags, err := parseStructTag(typ, i) + if err != nil { + return nil, err + } + if tags.ignored { + continue + } + info, err := cachedTypeInfo1(f.Type, tags) + if err != nil { + return nil, err + } + fields = append(fields, field{i, info}) + } + } + return fields, nil +} + +func parseStructTag(typ reflect.Type, fi int) (tags, error) { + f := typ.Field(fi) + var ts tags + for _, t := range strings.Split(f.Tag.Get("rlp"), ",") { + switch t = strings.TrimSpace(t); t { + case "": + case "-": + ts.ignored = true + case "nil": + ts.nilOK = true + case "tail": + ts.tail = true + if fi != typ.NumField()-1 { + return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (must be on last field)`, typ, f.Name) + } + if f.Type.Kind() != reflect.Slice { + return ts, fmt.Errorf(`rlp: invalid struct tag "tail" for %v.%s (field type is not slice)`, typ, f.Name) + } + default: + return ts, fmt.Errorf("rlp: unknown struct tag %q on %v.%s", t, typ, f.Name) + } + } + return ts, nil +} + +func genTypeInfo(typ reflect.Type, tags tags) (info *typeinfo, err error) { + info = new(typeinfo) + if info.decoder, err = makeDecoder(typ, tags); err != nil { + return nil, err + } + if info.writer, err = makeWriter(typ, tags); err != nil { + return nil, err + } + return info, nil +} + +func isUint(k reflect.Kind) bool { + return k >= reflect.Uint && k <= reflect.Uintptr +} diff --git a/vendor/github.com/go-stack/stack/LICENSE.md b/vendor/github.com/go-stack/stack/LICENSE.md new file mode 100644 index 00000000..2abf98ea --- /dev/null +++ b/vendor/github.com/go-stack/stack/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Chris Hines + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/go-stack/stack/README.md b/vendor/github.com/go-stack/stack/README.md new file mode 100644 index 00000000..f11cccca --- /dev/null +++ b/vendor/github.com/go-stack/stack/README.md @@ -0,0 +1,38 @@ +[![GoDoc](https://godoc.org/github.com/go-stack/stack?status.svg)](https://godoc.org/github.com/go-stack/stack) +[![Go Report Card](https://goreportcard.com/badge/go-stack/stack)](https://goreportcard.com/report/go-stack/stack) +[![TravisCI](https://travis-ci.org/go-stack/stack.svg?branch=master)](https://travis-ci.org/go-stack/stack) +[![Coverage Status](https://coveralls.io/repos/github/go-stack/stack/badge.svg?branch=master)](https://coveralls.io/github/go-stack/stack?branch=master) + +# stack + +Package stack implements utilities to capture, manipulate, and format call +stacks. It provides a simpler API than package runtime. + +The implementation takes care of the minutia and special cases of interpreting +the program counter (pc) values returned by runtime.Callers. + +## Versioning + +Package stack publishes releases via [semver](http://semver.org/) compatible Git +tags prefixed with a single 'v'. The master branch always contains the latest +release. The develop branch contains unreleased commits. + +## Formatting + +Package stack's types implement fmt.Formatter, which provides a simple and +flexible way to declaratively configure formatting when used with logging or +error tracking packages. + +```go +func DoTheThing() { + c := stack.Caller(0) + log.Print(c) // "source.go:10" + log.Printf("%+v", c) // "pkg/path/source.go:10" + log.Printf("%n", c) // "DoTheThing" + + s := stack.Trace().TrimRuntime() + log.Print(s) // "[source.go:15 caller.go:42 main.go:14]" +} +``` + +See the docs for all of the supported formatting options. diff --git a/vendor/github.com/go-stack/stack/stack.go b/vendor/github.com/go-stack/stack/stack.go new file mode 100644 index 00000000..a614eeeb --- /dev/null +++ b/vendor/github.com/go-stack/stack/stack.go @@ -0,0 +1,349 @@ +// Package stack implements utilities to capture, manipulate, and format call +// stacks. It provides a simpler API than package runtime. +// +// The implementation takes care of the minutia and special cases of +// interpreting the program counter (pc) values returned by runtime.Callers. +// +// Package stack's types implement fmt.Formatter, which provides a simple and +// flexible way to declaratively configure formatting when used with logging +// or error tracking packages. +package stack + +import ( + "bytes" + "errors" + "fmt" + "io" + "runtime" + "strconv" + "strings" +) + +// Call records a single function invocation from a goroutine stack. +type Call struct { + fn *runtime.Func + pc uintptr +} + +// Caller returns a Call from the stack of the current goroutine. The argument +// skip is the number of stack frames to ascend, with 0 identifying the +// calling function. +func Caller(skip int) Call { + var pcs [2]uintptr + n := runtime.Callers(skip+1, pcs[:]) + + var c Call + + if n < 2 { + return c + } + + c.pc = pcs[1] + if runtime.FuncForPC(pcs[0]) != sigpanic { + c.pc-- + } + c.fn = runtime.FuncForPC(c.pc) + return c +} + +// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", c). +func (c Call) String() string { + return fmt.Sprint(c) +} + +// MarshalText implements encoding.TextMarshaler. It formats the Call the same +// as fmt.Sprintf("%v", c). +func (c Call) MarshalText() ([]byte, error) { + if c.fn == nil { + return nil, ErrNoFunc + } + buf := bytes.Buffer{} + fmt.Fprint(&buf, c) + return buf.Bytes(), nil +} + +// ErrNoFunc means that the Call has a nil *runtime.Func. The most likely +// cause is a Call with the zero value. +var ErrNoFunc = errors.New("no call stack information") + +// Format implements fmt.Formatter with support for the following verbs. +// +// %s source file +// %d line number +// %n function name +// %v equivalent to %s:%d +// +// It accepts the '+' and '#' flags for most of the verbs as follows. +// +// %+s path of source file relative to the compile time GOPATH +// %#s full path of source file +// %+n import path qualified function name +// %+v equivalent to %+s:%d +// %#v equivalent to %#s:%d +func (c Call) Format(s fmt.State, verb rune) { + if c.fn == nil { + fmt.Fprintf(s, "%%!%c(NOFUNC)", verb) + return + } + + switch verb { + case 's', 'v': + file, line := c.fn.FileLine(c.pc) + switch { + case s.Flag('#'): + // done + case s.Flag('+'): + file = file[pkgIndex(file, c.fn.Name()):] + default: + const sep = "/" + if i := strings.LastIndex(file, sep); i != -1 { + file = file[i+len(sep):] + } + } + io.WriteString(s, file) + if verb == 'v' { + buf := [7]byte{':'} + s.Write(strconv.AppendInt(buf[:1], int64(line), 10)) + } + + case 'd': + _, line := c.fn.FileLine(c.pc) + buf := [6]byte{} + s.Write(strconv.AppendInt(buf[:0], int64(line), 10)) + + case 'n': + name := c.fn.Name() + if !s.Flag('+') { + const pathSep = "/" + if i := strings.LastIndex(name, pathSep); i != -1 { + name = name[i+len(pathSep):] + } + const pkgSep = "." + if i := strings.Index(name, pkgSep); i != -1 { + name = name[i+len(pkgSep):] + } + } + io.WriteString(s, name) + } +} + +// PC returns the program counter for this call frame; multiple frames may +// have the same PC value. +func (c Call) PC() uintptr { + return c.pc +} + +// name returns the import path qualified name of the function containing the +// call. +func (c Call) name() string { + if c.fn == nil { + return "???" + } + return c.fn.Name() +} + +func (c Call) file() string { + if c.fn == nil { + return "???" + } + file, _ := c.fn.FileLine(c.pc) + return file +} + +func (c Call) line() int { + if c.fn == nil { + return 0 + } + _, line := c.fn.FileLine(c.pc) + return line +} + +// CallStack records a sequence of function invocations from a goroutine +// stack. +type CallStack []Call + +// String implements fmt.Stinger. It is equivalent to fmt.Sprintf("%v", cs). +func (cs CallStack) String() string { + return fmt.Sprint(cs) +} + +var ( + openBracketBytes = []byte("[") + closeBracketBytes = []byte("]") + spaceBytes = []byte(" ") +) + +// MarshalText implements encoding.TextMarshaler. It formats the CallStack the +// same as fmt.Sprintf("%v", cs). +func (cs CallStack) MarshalText() ([]byte, error) { + buf := bytes.Buffer{} + buf.Write(openBracketBytes) + for i, pc := range cs { + if pc.fn == nil { + return nil, ErrNoFunc + } + if i > 0 { + buf.Write(spaceBytes) + } + fmt.Fprint(&buf, pc) + } + buf.Write(closeBracketBytes) + return buf.Bytes(), nil +} + +// Format implements fmt.Formatter by printing the CallStack as square brackets +// ([, ]) surrounding a space separated list of Calls each formatted with the +// supplied verb and options. +func (cs CallStack) Format(s fmt.State, verb rune) { + s.Write(openBracketBytes) + for i, pc := range cs { + if i > 0 { + s.Write(spaceBytes) + } + pc.Format(s, verb) + } + s.Write(closeBracketBytes) +} + +// findSigpanic intentionally executes faulting code to generate a stack trace +// containing an entry for runtime.sigpanic. +func findSigpanic() *runtime.Func { + var fn *runtime.Func + var p *int + func() int { + defer func() { + if p := recover(); p != nil { + var pcs [512]uintptr + n := runtime.Callers(2, pcs[:]) + for _, pc := range pcs[:n] { + f := runtime.FuncForPC(pc) + if f.Name() == "runtime.sigpanic" { + fn = f + break + } + } + } + }() + // intentional nil pointer dereference to trigger sigpanic + return *p + }() + return fn +} + +var sigpanic = findSigpanic() + +// Trace returns a CallStack for the current goroutine with element 0 +// identifying the calling function. +func Trace() CallStack { + var pcs [512]uintptr + n := runtime.Callers(2, pcs[:]) + cs := make([]Call, n) + + for i, pc := range pcs[:n] { + pcFix := pc + if i > 0 && cs[i-1].fn != sigpanic { + pcFix-- + } + cs[i] = Call{ + fn: runtime.FuncForPC(pcFix), + pc: pcFix, + } + } + + return cs +} + +// TrimBelow returns a slice of the CallStack with all entries below c +// removed. +func (cs CallStack) TrimBelow(c Call) CallStack { + for len(cs) > 0 && cs[0].pc != c.pc { + cs = cs[1:] + } + return cs +} + +// TrimAbove returns a slice of the CallStack with all entries above c +// removed. +func (cs CallStack) TrimAbove(c Call) CallStack { + for len(cs) > 0 && cs[len(cs)-1].pc != c.pc { + cs = cs[:len(cs)-1] + } + return cs +} + +// pkgIndex returns the index that results in file[index:] being the path of +// file relative to the compile time GOPATH, and file[:index] being the +// $GOPATH/src/ portion of file. funcName must be the name of a function in +// file as returned by runtime.Func.Name. +func pkgIndex(file, funcName string) int { + // As of Go 1.6.2 there is no direct way to know the compile time GOPATH + // at runtime, but we can infer the number of path segments in the GOPATH. + // We note that runtime.Func.Name() returns the function name qualified by + // the import path, which does not include the GOPATH. Thus we can trim + // segments from the beginning of the file path until the number of path + // separators remaining is one more than the number of path separators in + // the function name. For example, given: + // + // GOPATH /home/user + // file /home/user/src/pkg/sub/file.go + // fn.Name() pkg/sub.Type.Method + // + // We want to produce: + // + // file[:idx] == /home/user/src/ + // file[idx:] == pkg/sub/file.go + // + // From this we can easily see that fn.Name() has one less path separator + // than our desired result for file[idx:]. We count separators from the + // end of the file path until it finds two more than in the function name + // and then move one character forward to preserve the initial path + // segment without a leading separator. + const sep = "/" + i := len(file) + for n := strings.Count(funcName, sep) + 2; n > 0; n-- { + i = strings.LastIndex(file[:i], sep) + if i == -1 { + i = -len(sep) + break + } + } + // get back to 0 or trim the leading separator + return i + len(sep) +} + +var runtimePath string + +func init() { + var pcs [1]uintptr + runtime.Callers(0, pcs[:]) + fn := runtime.FuncForPC(pcs[0]) + file, _ := fn.FileLine(pcs[0]) + + idx := pkgIndex(file, fn.Name()) + + runtimePath = file[:idx] + if runtime.GOOS == "windows" { + runtimePath = strings.ToLower(runtimePath) + } +} + +func inGoroot(c Call) bool { + file := c.file() + if len(file) == 0 || file[0] == '?' { + return true + } + if runtime.GOOS == "windows" { + file = strings.ToLower(file) + } + return strings.HasPrefix(file, runtimePath) || strings.HasSuffix(file, "/_testmain.go") +} + +// TrimRuntime returns a slice of the CallStack with the topmost entries from +// the go runtime removed. It considers any calls originating from unknown +// files, files under GOROOT, or _testmain.go as part of the runtime. +func (cs CallStack) TrimRuntime() CallStack { + for len(cs) > 0 && inGoroot(cs[len(cs)-1]) { + cs = cs[:len(cs)-1] + } + return cs +} diff --git a/vendor/github.com/naoina/go-stringutil/LICENSE b/vendor/github.com/naoina/go-stringutil/LICENSE new file mode 100644 index 00000000..0fff1c58 --- /dev/null +++ b/vendor/github.com/naoina/go-stringutil/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 Naoya Inada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/naoina/go-stringutil/README.md b/vendor/github.com/naoina/go-stringutil/README.md new file mode 100644 index 00000000..ecf7a5fa --- /dev/null +++ b/vendor/github.com/naoina/go-stringutil/README.md @@ -0,0 +1,13 @@ +# stringutil [![Build Status](https://travis-ci.org/naoina/go-stringutil.svg?branch=master)](https://travis-ci.org/naoina/go-stringutil) + +## Installation + + go get -u github.com/naoina/go-stringutil + +## Documentation + +See https://godoc.org/github.com/naoina/go-stringutil + +## License + +MIT diff --git a/vendor/github.com/naoina/go-stringutil/da.go b/vendor/github.com/naoina/go-stringutil/da.go new file mode 100644 index 00000000..8fe65165 --- /dev/null +++ b/vendor/github.com/naoina/go-stringutil/da.go @@ -0,0 +1,253 @@ +package stringutil + +import ( + "fmt" + "sort" + "unicode/utf8" +) + +const ( + terminationCharacter = '#' +) + +func mustDoubleArray(da *doubleArray, err error) *doubleArray { + if err != nil { + panic(err) + } + return da +} + +func (da *doubleArray) Build(keys []string) error { + records := makeRecords(keys) + if err := da.build(records, 1, 0, make(map[int]struct{})); err != nil { + return err + } + return nil +} + +type doubleArray struct { + bc []baseCheck + node []int +} + +func newDoubleArray(keys []string) (*doubleArray, error) { + da := &doubleArray{ + bc: []baseCheck{0}, + node: []int{-1}, // A start index is adjusting to 1 because 0 will be used as a mark of non-existent node. + } + if err := da.Build(keys); err != nil { + return nil, err + } + return da, nil +} + +// baseCheck contains BASE, CHECK and Extra flags. +// From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK. +// +// BASE (22bit) | Extra flags (2bit) | CHECK (8bit) +// |----------------------|--|--------| +// 32 10 8 0 +type baseCheck uint32 + +func (bc baseCheck) Base() int { + return int(bc >> 10) +} + +func (bc *baseCheck) SetBase(base int) { + *bc |= baseCheck(base) << 10 +} + +func (bc baseCheck) Check() byte { + return byte(bc) +} + +func (bc *baseCheck) SetCheck(check byte) { + *bc |= baseCheck(check) +} + +func (bc baseCheck) IsEmpty() bool { + return bc&0xfffffcff == 0 +} + +func (da *doubleArray) Lookup(path string) (length int) { + idx := 1 + tmpIdx := idx + for i := 0; i < len(path); i++ { + c := path[i] + tmpIdx = da.nextIndex(da.bc[tmpIdx].Base(), c) + if tmpIdx >= len(da.bc) || da.bc[tmpIdx].Check() != c { + break + } + idx = tmpIdx + } + if next := da.nextIndex(da.bc[idx].Base(), terminationCharacter); next < len(da.bc) && da.bc[next].Check() == terminationCharacter { + return da.node[da.bc[next].Base()] + } + return -1 +} + +func (da *doubleArray) LookupByBytes(path []byte) (length int) { + idx := 1 + tmpIdx := idx + for i := 0; i < len(path); i++ { + c := path[i] + tmpIdx = da.nextIndex(da.bc[tmpIdx].Base(), c) + if tmpIdx >= len(da.bc) || da.bc[tmpIdx].Check() != c { + break + } + idx = tmpIdx + } + if next := da.nextIndex(da.bc[idx].Base(), terminationCharacter); next < len(da.bc) && da.bc[next].Check() == terminationCharacter { + return da.node[da.bc[next].Base()] + } + return -1 +} + +func (da *doubleArray) build(srcs []record, idx, depth int, usedBase map[int]struct{}) error { + sort.Stable(recordSlice(srcs)) + base, siblings, leaf, err := da.arrange(srcs, idx, depth, usedBase) + if err != nil { + return err + } + if leaf != nil { + da.bc[idx].SetBase(len(da.node)) + da.node = append(da.node, leaf.value) + } + for _, sib := range siblings { + da.setCheck(da.nextIndex(base, sib.c), sib.c) + } + for _, sib := range siblings { + if err := da.build(srcs[sib.start:sib.end], da.nextIndex(base, sib.c), depth+1, usedBase); err != nil { + return err + } + } + return nil +} + +func (da *doubleArray) setBase(i, base int) { + da.bc[i].SetBase(base) +} + +func (da *doubleArray) setCheck(i int, check byte) { + da.bc[i].SetCheck(check) +} + +func (da *doubleArray) findEmptyIndex(start int) int { + i := start + for ; i < len(da.bc); i++ { + if da.bc[i].IsEmpty() { + break + } + } + return i +} + +// findBase returns good BASE. +func (da *doubleArray) findBase(siblings []sibling, start int, usedBase map[int]struct{}) (base int) { + for idx, firstChar := start+1, siblings[0].c; ; idx = da.findEmptyIndex(idx + 1) { + base = da.nextIndex(idx, firstChar) + if _, used := usedBase[base]; used { + continue + } + i := 0 + for ; i < len(siblings); i++ { + next := da.nextIndex(base, siblings[i].c) + if len(da.bc) <= next { + da.bc = append(da.bc, make([]baseCheck, next-len(da.bc)+1)...) + } + if !da.bc[next].IsEmpty() { + break + } + } + if i == len(siblings) { + break + } + } + usedBase[base] = struct{}{} + return base +} + +func (da *doubleArray) arrange(records []record, idx, depth int, usedBase map[int]struct{}) (base int, siblings []sibling, leaf *record, err error) { + siblings, leaf, err = makeSiblings(records, depth) + if err != nil { + return -1, nil, nil, err + } + if len(siblings) < 1 { + return -1, nil, leaf, nil + } + base = da.findBase(siblings, idx, usedBase) + da.setBase(idx, base) + return base, siblings, leaf, err +} + +type sibling struct { + start int + end int + c byte +} + +func (da *doubleArray) nextIndex(base int, c byte) int { + return base ^ int(c) +} + +func makeSiblings(records []record, depth int) (sib []sibling, leaf *record, err error) { + var ( + pc byte + n int + ) + for i, r := range records { + if len(r.key) <= depth { + leaf = &r + continue + } + c := r.key[depth] + switch { + case pc < c: + sib = append(sib, sibling{start: i, c: c}) + case pc == c: + continue + default: + return nil, nil, fmt.Errorf("stringutil: BUG: records hasn't been sorted") + } + if n > 0 { + sib[n-1].end = i + } + pc = c + n++ + } + if n == 0 { + return nil, leaf, nil + } + sib[n-1].end = len(records) + return sib, leaf, nil +} + +type record struct { + key string + value int +} + +func makeRecords(srcs []string) (records []record) { + termChar := string(terminationCharacter) + for _, s := range srcs { + records = append(records, record{ + key: string(s + termChar), + value: utf8.RuneCountInString(s), + }) + } + return records +} + +type recordSlice []record + +func (rs recordSlice) Len() int { + return len(rs) +} + +func (rs recordSlice) Less(i, j int) bool { + return rs[i].key < rs[j].key +} + +func (rs recordSlice) Swap(i, j int) { + rs[i], rs[j] = rs[j], rs[i] +} diff --git a/vendor/github.com/naoina/go-stringutil/strings.go b/vendor/github.com/naoina/go-stringutil/strings.go new file mode 100644 index 00000000..881ca2c8 --- /dev/null +++ b/vendor/github.com/naoina/go-stringutil/strings.go @@ -0,0 +1,320 @@ +package stringutil + +import ( + "sync" + "unicode" + "unicode/utf8" +) + +var ( + mu sync.Mutex + + // Based on https://github.com/golang/lint/blob/32a87160691b3c96046c0c678fe57c5bef761456/lint.go#L702 + commonInitialismMap = map[string]struct{}{ + "API": struct{}{}, + "ASCII": struct{}{}, + "CPU": struct{}{}, + "CSRF": struct{}{}, + "CSS": struct{}{}, + "DNS": struct{}{}, + "EOF": struct{}{}, + "GUID": struct{}{}, + "HTML": struct{}{}, + "HTTP": struct{}{}, + "HTTPS": struct{}{}, + "ID": struct{}{}, + "IP": struct{}{}, + "JSON": struct{}{}, + "LHS": struct{}{}, + "QPS": struct{}{}, + "RAM": struct{}{}, + "RHS": struct{}{}, + "RPC": struct{}{}, + "SLA": struct{}{}, + "SMTP": struct{}{}, + "SQL": struct{}{}, + "SSH": struct{}{}, + "TCP": struct{}{}, + "TLS": struct{}{}, + "TTL": struct{}{}, + "UDP": struct{}{}, + "UI": struct{}{}, + "UID": struct{}{}, + "UUID": struct{}{}, + "URI": struct{}{}, + "URL": struct{}{}, + "UTF8": struct{}{}, + "VM": struct{}{}, + "XML": struct{}{}, + "XSRF": struct{}{}, + "XSS": struct{}{}, + } + commonInitialisms = keys(commonInitialismMap) + commonInitialism = mustDoubleArray(newDoubleArray(commonInitialisms)) + longestLen = longestLength(commonInitialisms) + shortestLen = shortestLength(commonInitialisms, longestLen) +) + +// ToUpperCamelCase returns a copy of the string s with all Unicode letters mapped to their camel case. +// It will convert to upper case previous letter of '_' and first letter, and remove letter of '_'. +func ToUpperCamelCase(s string) string { + if s == "" { + return "" + } + upper := true + start := 0 + result := make([]byte, 0, len(s)) + var runeBuf [utf8.UTFMax]byte + var initialism []byte + for _, c := range s { + if c == '_' { + upper = true + candidate := string(result[start:]) + initialism = initialism[:0] + for _, r := range candidate { + if r < utf8.RuneSelf { + initialism = append(initialism, toUpperASCII(byte(r))) + } else { + n := utf8.EncodeRune(runeBuf[:], unicode.ToUpper(r)) + initialism = append(initialism, runeBuf[:n]...) + } + } + if length := commonInitialism.LookupByBytes(initialism); length > 0 { + result = append(result[:start], initialism...) + } + start = len(result) + continue + } + if upper { + if c < utf8.RuneSelf { + result = append(result, toUpperASCII(byte(c))) + } else { + n := utf8.EncodeRune(runeBuf[:], unicode.ToUpper(c)) + result = append(result, runeBuf[:n]...) + } + upper = false + continue + } + if c < utf8.RuneSelf { + result = append(result, byte(c)) + } else { + n := utf8.EncodeRune(runeBuf[:], c) + result = append(result, runeBuf[:n]...) + } + } + candidate := string(result[start:]) + initialism = initialism[:0] + for _, r := range candidate { + if r < utf8.RuneSelf { + initialism = append(initialism, toUpperASCII(byte(r))) + } else { + n := utf8.EncodeRune(runeBuf[:], unicode.ToUpper(r)) + initialism = append(initialism, runeBuf[:n]...) + } + } + if length := commonInitialism.LookupByBytes(initialism); length > 0 { + result = append(result[:start], initialism...) + } + return string(result) +} + +// ToUpperCamelCaseASCII is similar to ToUpperCamelCase, but optimized for +// only the ASCII characters. +// ToUpperCamelCaseASCII is faster than ToUpperCamelCase, but doesn't work if +// contains non-ASCII characters. +func ToUpperCamelCaseASCII(s string) string { + if s == "" { + return "" + } + upper := true + start := 0 + result := make([]byte, 0, len(s)) + var initialism []byte + for i := 0; i < len(s); i++ { + c := s[i] + if c == '_' { + upper = true + candidate := result[start:] + initialism = initialism[:0] + for _, b := range candidate { + initialism = append(initialism, toUpperASCII(b)) + } + if length := commonInitialism.LookupByBytes(initialism); length > 0 { + result = append(result[:start], initialism...) + } + start = len(result) + continue + } + if upper { + result = append(result, toUpperASCII(c)) + upper = false + continue + } + result = append(result, c) + } + candidate := result[start:] + initialism = initialism[:0] + for _, b := range candidate { + initialism = append(initialism, toUpperASCII(b)) + } + if length := commonInitialism.LookupByBytes(initialism); length > 0 { + result = append(result[:start], initialism...) + } + return string(result) +} + +// ToSnakeCase returns a copy of the string s with all Unicode letters mapped to their snake case. +// It will insert letter of '_' at position of previous letter of uppercase and all +// letters convert to lower case. +// ToSnakeCase does not insert '_' letter into a common initialism word like ID, URL and so on. +func ToSnakeCase(s string) string { + if s == "" { + return "" + } + result := make([]byte, 0, len(s)) + var runeBuf [utf8.UTFMax]byte + var j, skipCount int + for i, c := range s { + if i < skipCount { + continue + } + if unicode.IsUpper(c) { + if i != 0 { + result = append(result, '_') + } + next := nextIndex(j, len(s)) + if length := commonInitialism.Lookup(s[j:next]); length > 0 { + for _, r := range s[j : j+length] { + if r < utf8.RuneSelf { + result = append(result, toLowerASCII(byte(r))) + } else { + n := utf8.EncodeRune(runeBuf[:], unicode.ToLower(r)) + result = append(result, runeBuf[:n]...) + } + } + j += length - 1 + skipCount = i + length + continue + } + } + if c < utf8.RuneSelf { + result = append(result, toLowerASCII(byte(c))) + } else { + n := utf8.EncodeRune(runeBuf[:], unicode.ToLower(c)) + result = append(result, runeBuf[:n]...) + } + j++ + } + return string(result) +} + +// ToSnakeCaseASCII is similar to ToSnakeCase, but optimized for only the ASCII +// characters. +// ToSnakeCaseASCII is faster than ToSnakeCase, but doesn't work correctly if +// contains non-ASCII characters. +func ToSnakeCaseASCII(s string) string { + if s == "" { + return "" + } + result := make([]byte, 0, len(s)) + for i := 0; i < len(s); i++ { + c := s[i] + if isUpperASCII(c) { + if i != 0 { + result = append(result, '_') + } + if k := i + shortestLen - 1; k < len(s) && isUpperASCII(s[k]) { + if length := commonInitialism.Lookup(s[i:nextIndex(i, len(s))]); length > 0 { + for j, buf := 0, s[i:i+length]; j < len(buf); j++ { + result = append(result, toLowerASCII(buf[j])) + } + i += length - 1 + continue + } + } + } + result = append(result, toLowerASCII(c)) + } + return string(result) +} + +// AddCommonInitialism adds ss to list of common initialisms. +func AddCommonInitialism(ss ...string) { + mu.Lock() + defer mu.Unlock() + for _, s := range ss { + commonInitialismMap[s] = struct{}{} + } + commonInitialisms = keys(commonInitialismMap) + commonInitialism = mustDoubleArray(newDoubleArray(commonInitialisms)) + longestLen = longestLength(commonInitialisms) + shortestLen = shortestLength(commonInitialisms, longestLen) +} + +// DelCommonInitialism deletes ss from list of common initialisms. +func DelCommonInitialism(ss ...string) { + mu.Lock() + defer mu.Unlock() + for _, s := range ss { + delete(commonInitialismMap, s) + } + commonInitialisms = keys(commonInitialismMap) + commonInitialism = mustDoubleArray(newDoubleArray(commonInitialisms)) + longestLen = longestLength(commonInitialisms) + shortestLen = shortestLength(commonInitialisms, longestLen) +} + +func isUpperASCII(c byte) bool { + return 'A' <= c && c <= 'Z' +} + +func isLowerASCII(c byte) bool { + return 'a' <= c && c <= 'z' +} + +func toUpperASCII(c byte) byte { + if isLowerASCII(c) { + return c - ('a' - 'A') + } + return c +} + +func toLowerASCII(c byte) byte { + if isUpperASCII(c) { + return c + 'a' - 'A' + } + return c +} + +func nextIndex(i, maxlen int) int { + if n := i + longestLen; n < maxlen { + return n + } + return maxlen +} + +func keys(m map[string]struct{}) []string { + result := make([]string, 0, len(m)) + for k := range m { + result = append(result, k) + } + return result +} + +func shortestLength(strs []string, shortest int) int { + for _, s := range strs { + if candidate := utf8.RuneCountInString(s); candidate < shortest { + shortest = candidate + } + } + return shortest +} + +func longestLength(strs []string) (longest int) { + for _, s := range strs { + if candidate := utf8.RuneCountInString(s); candidate > longest { + longest = candidate + } + } + return longest +} diff --git a/vendor/github.com/naoina/toml/LICENSE b/vendor/github.com/naoina/toml/LICENSE new file mode 100644 index 00000000..e65039ad --- /dev/null +++ b/vendor/github.com/naoina/toml/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Naoya Inada + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/naoina/toml/README.md b/vendor/github.com/naoina/toml/README.md new file mode 100644 index 00000000..1c014334 --- /dev/null +++ b/vendor/github.com/naoina/toml/README.md @@ -0,0 +1,392 @@ +# TOML parser and encoder library for Golang [![Build Status](https://travis-ci.org/naoina/toml.png?branch=master)](https://travis-ci.org/naoina/toml) + +[TOML](https://github.com/toml-lang/toml) parser and encoder library for [Golang](http://golang.org/). + +This library is compatible with TOML version [v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md). + +## Installation + + go get -u github.com/naoina/toml + +## Usage + +The following TOML save as `example.toml`. + +```toml +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Lance Uppercut" +dob = 1979-05-27T07:32:00-08:00 # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] + +# Line breaks are OK when inside arrays +hosts = [ + "alpha", + "omega" +] +``` + +Then above TOML will mapping to `tomlConfig` struct using `toml.Unmarshal`. + +```go +package main + +import ( + "io/ioutil" + "os" + "time" + + "github.com/naoina/toml" +) + +type tomlConfig struct { + Title string + Owner struct { + Name string + Dob time.Time + } + Database struct { + Server string + Ports []int + ConnectionMax uint + Enabled bool + } + Servers map[string]ServerInfo + Clients struct { + Data [][]interface{} + Hosts []string + } +} + +type ServerInfo struct { + IP net.IP + DC string +} + +func main() { + f, err := os.Open("example.toml") + if err != nil { + panic(err) + } + defer f.Close() + var config Config + if err := toml.NewDecoder(f).Decode(&config); err != nil { + panic(err) + } + + // then to use the unmarshaled config... + fmt.Println("IP of server 'alpha':", config.Servers["alpha"].IP) +} +``` + +## Mappings + +A key and value of TOML will map to the corresponding field. +The fields of struct for mapping must be exported. + +The rules of the mapping of key are following: + +#### Exact matching + +```toml +timeout_seconds = 256 +``` + +```go +type Config struct { + Timeout_seconds int +} +``` + +#### Camelcase matching + +```toml +server_name = "srv1" +``` + +```go +type Config struct { + ServerName string +} +``` + +#### Uppercase matching + +```toml +ip = "10.0.0.1" +``` + +```go +type Config struct { + IP string +} +``` + +See the following examples for the value mappings. + +### String + +```toml +val = "string" +``` + +```go +type Config struct { + Val string +} +``` + +### Integer + +```toml +val = 100 +``` + +```go +type Config struct { + Val int +} +``` + +All types that can be used are following: + +* int8 (from `-128` to `127`) +* int16 (from `-32768` to `32767`) +* int32 (from `-2147483648` to `2147483647`) +* int64 (from `-9223372036854775808` to `9223372036854775807`) +* int (same as `int32` on 32bit environment, or `int64` on 64bit environment) +* uint8 (from `0` to `255`) +* uint16 (from `0` to `65535`) +* uint32 (from `0` to `4294967295`) +* uint64 (from `0` to `18446744073709551615`) +* uint (same as `uint` on 32bit environment, or `uint64` on 64bit environment) + +### Float + +```toml +val = 3.1415 +``` + +```go +type Config struct { + Val float32 +} +``` + +All types that can be used are following: + +* float32 +* float64 + +### Boolean + +```toml +val = true +``` + +```go +type Config struct { + Val bool +} +``` + +### Datetime + +```toml +val = 2014-09-28T21:27:39Z +``` + +```go +type Config struct { + Val time.Time +} +``` + +### Array + +```toml +val = ["a", "b", "c"] +``` + +```go +type Config struct { + Val []string +} +``` + +Also following examples all can be mapped: + +```toml +val1 = [1, 2, 3] +val2 = [["a", "b"], ["c", "d"]] +val3 = [[1, 2, 3], ["a", "b", "c"]] +val4 = [[1, 2, 3], [["a", "b"], [true, false]]] +``` + +```go +type Config struct { + Val1 []int + Val2 [][]string + Val3 [][]interface{} + Val4 [][]interface{} +} +``` + +### Table + +```toml +[server] +type = "app" + + [server.development] + ip = "10.0.0.1" + + [server.production] + ip = "10.0.0.2" +``` + +```go +type Config struct { + Server map[string]Server +} + +type Server struct { + IP string +} +``` + +You can also use the following struct instead of map of struct. + +```go +type Config struct { + Server struct { + Development Server + Production Server + } +} + +type Server struct { + IP string +} +``` + +### Array of Tables + +```toml +[[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + +[[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" +``` + +```go +type Config struct { + Fruit []struct { + Name string + Physical struct { + Color string + Shape string + } + Variety []struct { + Name string + } + } +} +``` + +### Using the `encoding.TextUnmarshaler` interface + +Package toml supports `encoding.TextUnmarshaler` (and `encoding.TextMarshaler`). You can +use it to apply custom marshaling rules for certain types. The `UnmarshalText` method is +called with the value text found in the TOML input. TOML strings are passed unquoted. + +```toml +duration = "10s" +``` + +```go +import time + +type Duration time.Duration + +// UnmarshalText implements encoding.TextUnmarshaler +func (d *Duration) UnmarshalText(data []byte) error { + duration, err := time.ParseDuration(string(data)) + if err == nil { + *d = Duration(duration) + } + return err +} + +// MarshalText implements encoding.TextMarshaler +func (d Duration) MarshalText() ([]byte, error) { + return []byte(time.Duration(d).String()), nil +} + +type ConfigWithDuration struct { + Duration Duration +} +``` +### Using the `toml.UnmarshalerRec` interface + +You can also override marshaling rules specifically for TOML using the `UnmarshalerRec` +and `MarshalerRec` interfaces. These are useful if you want to control how structs or +arrays are handled. You can apply additional validation or set unexported struct fields. + +Note: `encoding.TextUnmarshaler` and `encoding.TextMarshaler` should be preferred for +simple (scalar) values because they're also compatible with other formats like JSON or +YAML. + +[See the UnmarshalerRec example](https://godoc.org/github.com/naoina/toml/#example_UnmarshalerRec). + +### Using the `toml.Unmarshaler` interface + +If you want to deal with raw TOML syntax, use the `Unmarshaler` and `Marshaler` +interfaces. Their input and output is raw TOML syntax. As such, these interfaces are +useful if you want to handle TOML at the syntax level. + +[See the Unmarshaler example](https://godoc.org/github.com/naoina/toml/#example_Unmarshaler). + +## API documentation + +See [Godoc](http://godoc.org/github.com/naoina/toml). + +## License + +MIT diff --git a/vendor/github.com/naoina/toml/ast/ast.go b/vendor/github.com/naoina/toml/ast/ast.go new file mode 100644 index 00000000..4868e2e1 --- /dev/null +++ b/vendor/github.com/naoina/toml/ast/ast.go @@ -0,0 +1,192 @@ +package ast + +import ( + "strconv" + "strings" + "time" +) + +type Position struct { + Begin int + End int +} + +type Value interface { + Pos() int + End() int + Source() string +} + +type String struct { + Position Position + Value string + Data []rune +} + +func (s *String) Pos() int { + return s.Position.Begin +} + +func (s *String) End() int { + return s.Position.End +} + +func (s *String) Source() string { + return string(s.Data) +} + +type Integer struct { + Position Position + Value string + Data []rune +} + +func (i *Integer) Pos() int { + return i.Position.Begin +} + +func (i *Integer) End() int { + return i.Position.End +} + +func (i *Integer) Source() string { + return string(i.Data) +} + +func (i *Integer) Int() (int64, error) { + return strconv.ParseInt(i.Value, 10, 64) +} + +type Float struct { + Position Position + Value string + Data []rune +} + +func (f *Float) Pos() int { + return f.Position.Begin +} + +func (f *Float) End() int { + return f.Position.End +} + +func (f *Float) Source() string { + return string(f.Data) +} + +func (f *Float) Float() (float64, error) { + return strconv.ParseFloat(f.Value, 64) +} + +type Boolean struct { + Position Position + Value string + Data []rune +} + +func (b *Boolean) Pos() int { + return b.Position.Begin +} + +func (b *Boolean) End() int { + return b.Position.End +} + +func (b *Boolean) Source() string { + return string(b.Data) +} + +func (b *Boolean) Boolean() (bool, error) { + return strconv.ParseBool(b.Value) +} + +type Datetime struct { + Position Position + Value string + Data []rune +} + +func (d *Datetime) Pos() int { + return d.Position.Begin +} + +func (d *Datetime) End() int { + return d.Position.End +} + +func (d *Datetime) Source() string { + return string(d.Data) +} + +func (d *Datetime) Time() (time.Time, error) { + switch { + case !strings.Contains(d.Value, ":"): + return time.Parse("2006-01-02", d.Value) + case !strings.Contains(d.Value, "-"): + return time.Parse("15:04:05.999999999", d.Value) + default: + return time.Parse(time.RFC3339Nano, d.Value) + } +} + +type Array struct { + Position Position + Value []Value + Data []rune +} + +func (a *Array) Pos() int { + return a.Position.Begin +} + +func (a *Array) End() int { + return a.Position.End +} + +func (a *Array) Source() string { + return string(a.Data) +} + +type TableType uint8 + +const ( + TableTypeNormal TableType = iota + TableTypeArray +) + +var tableTypes = [...]string{ + "normal", + "array", +} + +func (t TableType) String() string { + return tableTypes[t] +} + +type Table struct { + Position Position + Line int + Name string + Fields map[string]interface{} + Type TableType + Data []rune +} + +func (t *Table) Pos() int { + return t.Position.Begin +} + +func (t *Table) End() int { + return t.Position.End +} + +func (t *Table) Source() string { + return string(t.Data) +} + +type KeyValue struct { + Key string + Value Value + Line int +} diff --git a/vendor/github.com/naoina/toml/config.go b/vendor/github.com/naoina/toml/config.go new file mode 100644 index 00000000..06bb9493 --- /dev/null +++ b/vendor/github.com/naoina/toml/config.go @@ -0,0 +1,86 @@ +package toml + +import ( + "fmt" + "io" + "reflect" + "strings" + + stringutil "github.com/naoina/go-stringutil" + "github.com/naoina/toml/ast" +) + +// Config contains options for encoding and decoding. +type Config struct { + // NormFieldName is used to match TOML keys to struct fields. The function runs for + // both input keys and struct field names and should return a string that makes the + // two match. You must set this field to use the decoder. + // + // Example: The function in the default config removes _ and lowercases all keys. This + // allows a key called 'api_key' to match the struct field 'APIKey' because both are + // normalized to 'apikey'. + // + // Note that NormFieldName is not used for fields which define a TOML + // key through the struct tag. + NormFieldName func(typ reflect.Type, keyOrField string) string + + // FieldToKey determines the TOML key of a struct field when encoding. + // You must set this field to use the encoder. + // + // Note that FieldToKey is not used for fields which define a TOML + // key through the struct tag. + FieldToKey func(typ reflect.Type, field string) string + + // MissingField, if non-nil, is called when the decoder encounters a key for which no + // matching struct field exists. The default behavior is to return an error. + MissingField func(typ reflect.Type, key string) error +} + +// DefaultConfig contains the default options for encoding and decoding. +// Snake case (i.e. 'foo_bar') is used for key names. +var DefaultConfig = Config{ + NormFieldName: defaultNormFieldName, + FieldToKey: snakeCase, +} + +func defaultNormFieldName(typ reflect.Type, s string) string { + return strings.Replace(strings.ToLower(s), "_", "", -1) +} + +func snakeCase(typ reflect.Type, s string) string { + return stringutil.ToSnakeCase(s) +} + +func defaultMissingField(typ reflect.Type, key string) error { + return fmt.Errorf("field corresponding to `%s' is not defined in %v", key, typ) +} + +// NewEncoder returns a new Encoder that writes to w. +// It is shorthand for DefaultConfig.NewEncoder(w). +func NewEncoder(w io.Writer) *Encoder { + return DefaultConfig.NewEncoder(w) +} + +// Marshal returns the TOML encoding of v. +// It is shorthand for DefaultConfig.Marshal(v). +func Marshal(v interface{}) ([]byte, error) { + return DefaultConfig.Marshal(v) +} + +// Unmarshal parses the TOML data and stores the result in the value pointed to by v. +// It is shorthand for DefaultConfig.Unmarshal(data, v). +func Unmarshal(data []byte, v interface{}) error { + return DefaultConfig.Unmarshal(data, v) +} + +// UnmarshalTable applies the contents of an ast.Table to the value pointed at by v. +// It is shorthand for DefaultConfig.UnmarshalTable(t, v). +func UnmarshalTable(t *ast.Table, v interface{}) error { + return DefaultConfig.UnmarshalTable(t, v) +} + +// NewDecoder returns a new Decoder that reads from r. +// It is shorthand for DefaultConfig.NewDecoder(r). +func NewDecoder(r io.Reader) *Decoder { + return DefaultConfig.NewDecoder(r) +} diff --git a/vendor/github.com/naoina/toml/decode.go b/vendor/github.com/naoina/toml/decode.go new file mode 100644 index 00000000..b3c169eb --- /dev/null +++ b/vendor/github.com/naoina/toml/decode.go @@ -0,0 +1,478 @@ +// Package toml encodes and decodes the TOML configuration format using reflection. +// +// This library is compatible with TOML version v0.4.0. +package toml + +import ( + "encoding" + "fmt" + "io" + "io/ioutil" + "reflect" + "strconv" + "strings" + "time" + + "github.com/naoina/toml/ast" +) + +const ( + tableSeparator = '.' +) + +var ( + escapeReplacer = strings.NewReplacer( + "\b", "\\n", + "\f", "\\f", + "\n", "\\n", + "\r", "\\r", + "\t", "\\t", + ) + underscoreReplacer = strings.NewReplacer( + "_", "", + ) +) + +var timeType = reflect.TypeOf(time.Time{}) + +// Unmarshal parses the TOML data and stores the result in the value pointed to by v. +// +// Unmarshal will mapped to v that according to following rules: +// +// TOML strings to string +// TOML integers to any int type +// TOML floats to float32 or float64 +// TOML booleans to bool +// TOML datetimes to time.Time +// TOML arrays to any type of slice +// TOML tables to struct or map +// TOML array tables to slice of struct or map +func (cfg *Config) Unmarshal(data []byte, v interface{}) error { + table, err := Parse(data) + if err != nil { + return err + } + if err := cfg.UnmarshalTable(table, v); err != nil { + return err + } + return nil +} + +// A Decoder reads and decodes TOML from an input stream. +type Decoder struct { + r io.Reader + cfg *Config +} + +// NewDecoder returns a new Decoder that reads from r. +// Note that it reads all from r before parsing it. +func (cfg *Config) NewDecoder(r io.Reader) *Decoder { + return &Decoder{r, cfg} +} + +// Decode parses the TOML data from its input and stores it in the value pointed to by v. +// See the documentation for Unmarshal for details about the conversion of TOML into a Go value. +func (d *Decoder) Decode(v interface{}) error { + b, err := ioutil.ReadAll(d.r) + if err != nil { + return err + } + return d.cfg.Unmarshal(b, v) +} + +// UnmarshalerRec may be implemented by types to customize their behavior when being +// unmarshaled from TOML. You can use it to implement custom validation or to set +// unexported fields. +// +// UnmarshalTOML receives a function that can be called to unmarshal the original TOML +// value into a field or variable. It is safe to call the function more than once if +// necessary. +type UnmarshalerRec interface { + UnmarshalTOML(fn func(interface{}) error) error +} + +// Unmarshaler can be used to capture and process raw TOML source of a table or value. +// UnmarshalTOML must copy the input if it wishes to retain it after returning. +// +// Note: this interface is retained for backwards compatibility. You probably want +// to implement encoding.TextUnmarshaler or UnmarshalerRec instead. +type Unmarshaler interface { + UnmarshalTOML(input []byte) error +} + +// UnmarshalTable applies the contents of an ast.Table to the value pointed at by v. +// +// UnmarshalTable will mapped to v that according to following rules: +// +// TOML strings to string +// TOML integers to any int type +// TOML floats to float32 or float64 +// TOML booleans to bool +// TOML datetimes to time.Time +// TOML arrays to any type of slice +// TOML tables to struct or map +// TOML array tables to slice of struct or map +func (cfg *Config) UnmarshalTable(t *ast.Table, v interface{}) error { + rv := reflect.ValueOf(v) + toplevelMap := rv.Kind() == reflect.Map + if (!toplevelMap && rv.Kind() != reflect.Ptr) || rv.IsNil() { + return &invalidUnmarshalError{reflect.TypeOf(v)} + } + return unmarshalTable(cfg, rv, t, toplevelMap) +} + +// used for UnmarshalerRec. +func unmarshalTableOrValue(cfg *Config, rv reflect.Value, av interface{}) error { + if (rv.Kind() != reflect.Ptr && rv.Kind() != reflect.Map) || rv.IsNil() { + return &invalidUnmarshalError{rv.Type()} + } + rv = indirect(rv) + + switch av.(type) { + case *ast.KeyValue, *ast.Table, []*ast.Table: + if err := unmarshalField(cfg, rv, av); err != nil { + return lineError(fieldLineNumber(av), err) + } + return nil + case ast.Value: + return setValue(cfg, rv, av.(ast.Value)) + default: + panic(fmt.Sprintf("BUG: unhandled AST node type %T", av)) + } +} + +// unmarshalTable unmarshals the fields of a table into a struct or map. +// +// toplevelMap is true when rv is an (unadressable) map given to UnmarshalTable. In this +// (special) case, the map is used as-is instead of creating a new map. +func unmarshalTable(cfg *Config, rv reflect.Value, t *ast.Table, toplevelMap bool) error { + rv = indirect(rv) + if err, ok := setUnmarshaler(cfg, rv, t); ok { + return lineError(t.Line, err) + } + switch { + case rv.Kind() == reflect.Struct: + fc := makeFieldCache(cfg, rv.Type()) + for key, fieldAst := range t.Fields { + fv, fieldName, err := fc.findField(cfg, rv, key) + if err != nil { + return lineError(fieldLineNumber(fieldAst), err) + } + if fv.IsValid() { + if err := unmarshalField(cfg, fv, fieldAst); err != nil { + return lineErrorField(fieldLineNumber(fieldAst), rv.Type().String()+"."+fieldName, err) + } + } + } + case rv.Kind() == reflect.Map || isEface(rv): + m := rv + if !toplevelMap { + if rv.Kind() == reflect.Interface { + m = reflect.ValueOf(make(map[string]interface{})) + } else { + m = reflect.MakeMap(rv.Type()) + } + } + elemtyp := m.Type().Elem() + for key, fieldAst := range t.Fields { + kv, err := unmarshalMapKey(m.Type().Key(), key) + if err != nil { + return lineError(fieldLineNumber(fieldAst), err) + } + fv := reflect.New(elemtyp).Elem() + if err := unmarshalField(cfg, fv, fieldAst); err != nil { + return lineError(fieldLineNumber(fieldAst), err) + } + m.SetMapIndex(kv, fv) + } + if !toplevelMap { + rv.Set(m) + } + default: + return lineError(t.Line, &unmarshalTypeError{"table", "struct or map", rv.Type()}) + } + return nil +} + +func fieldLineNumber(fieldAst interface{}) int { + switch av := fieldAst.(type) { + case *ast.KeyValue: + return av.Line + case *ast.Table: + return av.Line + case []*ast.Table: + return av[0].Line + default: + panic(fmt.Sprintf("BUG: unhandled node type %T", fieldAst)) + } +} + +func unmarshalField(cfg *Config, rv reflect.Value, fieldAst interface{}) error { + switch av := fieldAst.(type) { + case *ast.KeyValue: + return setValue(cfg, rv, av.Value) + case *ast.Table: + return unmarshalTable(cfg, rv, av, false) + case []*ast.Table: + rv = indirect(rv) + if err, ok := setUnmarshaler(cfg, rv, fieldAst); ok { + return err + } + var slice reflect.Value + switch { + case rv.Kind() == reflect.Slice: + slice = reflect.MakeSlice(rv.Type(), len(av), len(av)) + case isEface(rv): + slice = reflect.ValueOf(make([]interface{}, len(av))) + default: + return &unmarshalTypeError{"array table", "slice", rv.Type()} + } + for i, tbl := range av { + vv := reflect.New(slice.Type().Elem()).Elem() + if err := unmarshalTable(cfg, vv, tbl, false); err != nil { + return err + } + slice.Index(i).Set(vv) + } + rv.Set(slice) + default: + panic(fmt.Sprintf("BUG: unhandled AST node type %T", av)) + } + return nil +} + +func unmarshalMapKey(typ reflect.Type, key string) (reflect.Value, error) { + rv := reflect.New(typ).Elem() + if u, ok := rv.Addr().Interface().(encoding.TextUnmarshaler); ok { + return rv, u.UnmarshalText([]byte(key)) + } + switch typ.Kind() { + case reflect.String: + rv.SetString(key) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + i, err := strconv.ParseInt(key, 10, int(typ.Size()*8)) + if err != nil { + return rv, convertNumError(typ.Kind(), err) + } + rv.SetInt(i) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + i, err := strconv.ParseUint(key, 10, int(typ.Size()*8)) + if err != nil { + return rv, convertNumError(typ.Kind(), err) + } + rv.SetUint(i) + default: + return rv, fmt.Errorf("invalid map key type %s", typ) + } + return rv, nil +} + +func setValue(cfg *Config, lhs reflect.Value, val ast.Value) error { + lhs = indirect(lhs) + if err, ok := setUnmarshaler(cfg, lhs, val); ok { + return err + } + if err, ok := setTextUnmarshaler(lhs, val); ok { + return err + } + switch v := val.(type) { + case *ast.Integer: + return setInt(lhs, v) + case *ast.Float: + return setFloat(lhs, v) + case *ast.String: + return setString(lhs, v) + case *ast.Boolean: + return setBoolean(lhs, v) + case *ast.Datetime: + return setDatetime(lhs, v) + case *ast.Array: + return setArray(cfg, lhs, v) + default: + panic(fmt.Sprintf("BUG: unhandled node type %T", v)) + } +} + +func indirect(rv reflect.Value) reflect.Value { + for rv.Kind() == reflect.Ptr { + if rv.IsNil() { + rv.Set(reflect.New(rv.Type().Elem())) + } + rv = rv.Elem() + } + return rv +} + +func setUnmarshaler(cfg *Config, lhs reflect.Value, av interface{}) (error, bool) { + if lhs.CanAddr() { + if u, ok := lhs.Addr().Interface().(UnmarshalerRec); ok { + err := u.UnmarshalTOML(func(v interface{}) error { + return unmarshalTableOrValue(cfg, reflect.ValueOf(v), av) + }) + return err, true + } + if u, ok := lhs.Addr().Interface().(Unmarshaler); ok { + return u.UnmarshalTOML(unmarshalerSource(av)), true + } + } + return nil, false +} + +func unmarshalerSource(av interface{}) []byte { + var source []byte + switch av := av.(type) { + case []*ast.Table: + for i, tab := range av { + source = append(source, tab.Source()...) + if i != len(av)-1 { + source = append(source, '\n') + } + } + case ast.Value: + source = []byte(av.Source()) + default: + panic(fmt.Sprintf("BUG: unhandled node type %T", av)) + } + return source +} + +func setTextUnmarshaler(lhs reflect.Value, val ast.Value) (error, bool) { + if !lhs.CanAddr() { + return nil, false + } + u, ok := lhs.Addr().Interface().(encoding.TextUnmarshaler) + if !ok || lhs.Type() == timeType { + return nil, false + } + var data string + switch val := val.(type) { + case *ast.Array: + return &unmarshalTypeError{"array", "", lhs.Type()}, true + case *ast.String: + data = val.Value + default: + data = val.Source() + } + return u.UnmarshalText([]byte(data)), true +} + +func setInt(fv reflect.Value, v *ast.Integer) error { + k := fv.Kind() + switch { + case k >= reflect.Int && k <= reflect.Int64: + i, err := strconv.ParseInt(v.Value, 10, int(fv.Type().Size()*8)) + if err != nil { + return convertNumError(fv.Kind(), err) + } + fv.SetInt(i) + case k >= reflect.Uint && k <= reflect.Uintptr: + i, err := strconv.ParseUint(v.Value, 10, int(fv.Type().Size()*8)) + if err != nil { + return convertNumError(fv.Kind(), err) + } + fv.SetUint(i) + case isEface(fv): + i, err := strconv.ParseInt(v.Value, 10, 64) + if err != nil { + return convertNumError(reflect.Int64, err) + } + fv.Set(reflect.ValueOf(i)) + default: + return &unmarshalTypeError{"integer", "", fv.Type()} + } + return nil +} + +func setFloat(fv reflect.Value, v *ast.Float) error { + f, err := v.Float() + if err != nil { + return err + } + switch { + case fv.Kind() == reflect.Float32 || fv.Kind() == reflect.Float64: + if fv.OverflowFloat(f) { + return &overflowError{fv.Kind(), v.Value} + } + fv.SetFloat(f) + case isEface(fv): + fv.Set(reflect.ValueOf(f)) + default: + return &unmarshalTypeError{"float", "", fv.Type()} + } + return nil +} + +func setString(fv reflect.Value, v *ast.String) error { + switch { + case fv.Kind() == reflect.String: + fv.SetString(v.Value) + case isEface(fv): + fv.Set(reflect.ValueOf(v.Value)) + default: + return &unmarshalTypeError{"string", "", fv.Type()} + } + return nil +} + +func setBoolean(fv reflect.Value, v *ast.Boolean) error { + b, _ := v.Boolean() + switch { + case fv.Kind() == reflect.Bool: + fv.SetBool(b) + case isEface(fv): + fv.Set(reflect.ValueOf(b)) + default: + return &unmarshalTypeError{"boolean", "", fv.Type()} + } + return nil +} + +func setDatetime(rv reflect.Value, v *ast.Datetime) error { + t, err := v.Time() + if err != nil { + return err + } + if !timeType.AssignableTo(rv.Type()) { + return &unmarshalTypeError{"datetime", "", rv.Type()} + } + rv.Set(reflect.ValueOf(t)) + return nil +} + +func setArray(cfg *Config, rv reflect.Value, v *ast.Array) error { + var slicetyp reflect.Type + switch { + case rv.Kind() == reflect.Slice: + slicetyp = rv.Type() + case isEface(rv): + slicetyp = reflect.SliceOf(rv.Type()) + default: + return &unmarshalTypeError{"array", "slice", rv.Type()} + } + + if len(v.Value) == 0 { + // Ensure defined slices are always set to a non-nil value. + rv.Set(reflect.MakeSlice(slicetyp, 0, 0)) + return nil + } + + tomltyp := reflect.TypeOf(v.Value[0]) + slice := reflect.MakeSlice(slicetyp, len(v.Value), len(v.Value)) + typ := slicetyp.Elem() + for i, vv := range v.Value { + if i > 0 && tomltyp != reflect.TypeOf(vv) { + return errArrayMultiType + } + tmp := reflect.New(typ).Elem() + if err := setValue(cfg, tmp, vv); err != nil { + return err + } + slice.Index(i).Set(tmp) + } + rv.Set(slice) + return nil +} + +func isEface(rv reflect.Value) bool { + return rv.Kind() == reflect.Interface && rv.Type().NumMethod() == 0 +} diff --git a/vendor/github.com/naoina/toml/encode.go b/vendor/github.com/naoina/toml/encode.go new file mode 100644 index 00000000..ae6bfd57 --- /dev/null +++ b/vendor/github.com/naoina/toml/encode.go @@ -0,0 +1,398 @@ +package toml + +import ( + "bytes" + "encoding" + "fmt" + "io" + "reflect" + "sort" + "strconv" + "time" + + "github.com/naoina/toml/ast" +) + +const ( + tagOmitempty = "omitempty" + tagSkip = "-" +) + +// Marshal returns the TOML encoding of v. +// +// Struct values encode as TOML. Each exported struct field becomes a field of +// the TOML structure unless +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option. +// +// The "toml" key in the struct field's tag value is the key name, followed by +// an optional comma and options. Examples: +// +// // Field is ignored by this package. +// Field int `toml:"-"` +// +// // Field appears in TOML as key "myName". +// Field int `toml:"myName"` +// +// // Field appears in TOML as key "myName" and the field is omitted from the +// // result of encoding if its value is empty. +// Field int `toml:"myName,omitempty"` +// +// // Field appears in TOML as key "field", but the field is skipped if +// // empty. Note the leading comma. +// Field int `toml:",omitempty"` +func (cfg *Config) Marshal(v interface{}) ([]byte, error) { + buf := new(bytes.Buffer) + err := cfg.NewEncoder(buf).Encode(v) + return buf.Bytes(), err +} + +// A Encoder writes TOML to an output stream. +type Encoder struct { + w io.Writer + cfg *Config +} + +// NewEncoder returns a new Encoder that writes to w. +func (cfg *Config) NewEncoder(w io.Writer) *Encoder { + return &Encoder{w, cfg} +} + +// Encode writes the TOML of v to the stream. +// See the documentation for Marshal for details about the conversion of Go values to TOML. +func (e *Encoder) Encode(v interface{}) error { + rv := reflect.ValueOf(v) + for rv.Kind() == reflect.Ptr { + if rv.IsNil() { + return &marshalNilError{rv.Type()} + } + rv = rv.Elem() + } + buf := &tableBuf{typ: ast.TableTypeNormal} + var err error + switch rv.Kind() { + case reflect.Struct: + err = buf.structFields(e.cfg, rv) + case reflect.Map: + err = buf.mapFields(e.cfg, rv) + default: + err = &marshalTableError{rv.Type()} + } + if err != nil { + return err + } + return buf.writeTo(e.w, "") +} + +// Marshaler can be implemented to override the encoding of TOML values. The returned text +// must be a simple TOML value (i.e. not a table) and is inserted into marshaler output. +// +// This interface exists for backwards-compatibility reasons. You probably want to +// implement encoding.TextMarshaler or MarshalerRec instead. +type Marshaler interface { + MarshalTOML() ([]byte, error) +} + +// MarshalerRec can be implemented to override the TOML encoding of a type. +// The returned value is marshaled in place of the receiver. +type MarshalerRec interface { + MarshalTOML() (interface{}, error) +} + +type tableBuf struct { + name string // already escaped / quoted + body []byte + children []*tableBuf + typ ast.TableType + arrayDepth int +} + +func (b *tableBuf) writeTo(w io.Writer, prefix string) error { + key := b.name // TODO: escape dots + if prefix != "" { + key = prefix + "." + key + } + + if b.name != "" { + head := "[" + key + "]" + if b.typ == ast.TableTypeArray { + head = "[" + head + "]" + } + head += "\n" + if _, err := io.WriteString(w, head); err != nil { + return err + } + } + if _, err := w.Write(b.body); err != nil { + return err + } + + for i, child := range b.children { + if len(b.body) > 0 || i > 0 { + if _, err := w.Write([]byte("\n")); err != nil { + return err + } + } + if err := child.writeTo(w, key); err != nil { + return err + } + } + return nil +} + +func (b *tableBuf) newChild(name string) *tableBuf { + child := &tableBuf{name: quoteName(name), typ: ast.TableTypeNormal} + if b.arrayDepth > 0 { + child.typ = ast.TableTypeArray + } + return child +} + +func (b *tableBuf) addChild(child *tableBuf) { + // Empty table elision: we can avoid writing a table that doesn't have any keys on its + // own. Array tables can't be elided because they define array elements (which would + // be missing if elided). + if len(child.body) == 0 && child.typ == ast.TableTypeNormal { + for _, gchild := range child.children { + gchild.name = child.name + "." + gchild.name + b.addChild(gchild) + } + return + } + b.children = append(b.children, child) +} + +func (b *tableBuf) structFields(cfg *Config, rv reflect.Value) error { + rt := rv.Type() + for i := 0; i < rv.NumField(); i++ { + ft := rt.Field(i) + if ft.PkgPath != "" && !ft.Anonymous { // not exported + continue + } + name, rest := extractTag(ft.Tag.Get(fieldTagName)) + if name == tagSkip { + continue + } + fv := rv.Field(i) + if rest == tagOmitempty && isEmptyValue(fv) { + continue + } + if name == "" { + name = cfg.FieldToKey(rt, ft.Name) + } + if err := b.field(cfg, name, fv); err != nil { + return err + } + } + return nil +} + +type mapKeyList []struct { + key string + value reflect.Value +} + +func (l mapKeyList) Len() int { return len(l) } +func (l mapKeyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } +func (l mapKeyList) Less(i, j int) bool { return l[i].key < l[j].key } + +func (b *tableBuf) mapFields(cfg *Config, rv reflect.Value) error { + keys := rv.MapKeys() + keylist := make(mapKeyList, len(keys)) + for i, key := range keys { + var err error + keylist[i].key, err = encodeMapKey(key) + if err != nil { + return err + } + keylist[i].value = rv.MapIndex(key) + } + sort.Sort(keylist) + + for _, kv := range keylist { + if err := b.field(cfg, kv.key, kv.value); err != nil { + return err + } + } + return nil +} + +func (b *tableBuf) field(cfg *Config, name string, rv reflect.Value) error { + off := len(b.body) + b.body = append(b.body, quoteName(name)...) + b.body = append(b.body, " = "...) + isTable, err := b.value(cfg, rv, name) + if isTable { + b.body = b.body[:off] // rub out "key =" + } else { + b.body = append(b.body, '\n') + } + return err +} + +func (b *tableBuf) value(cfg *Config, rv reflect.Value, name string) (bool, error) { + isMarshaler, isTable, err := b.marshaler(cfg, rv, name) + if isMarshaler { + return isTable, err + } + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + b.body = strconv.AppendInt(b.body, rv.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + b.body = strconv.AppendUint(b.body, rv.Uint(), 10) + case reflect.Float32, reflect.Float64: + b.body = strconv.AppendFloat(b.body, rv.Float(), 'e', -1, 64) + case reflect.Bool: + b.body = strconv.AppendBool(b.body, rv.Bool()) + case reflect.String: + b.body = strconv.AppendQuote(b.body, rv.String()) + case reflect.Ptr, reflect.Interface: + if rv.IsNil() { + return false, &marshalNilError{rv.Type()} + } + return b.value(cfg, rv.Elem(), name) + case reflect.Slice, reflect.Array: + rvlen := rv.Len() + if rvlen == 0 { + b.body = append(b.body, '[', ']') + return false, nil + } + + b.arrayDepth++ + wroteElem := false + b.body = append(b.body, '[') + for i := 0; i < rvlen; i++ { + isTable, err := b.value(cfg, rv.Index(i), name) + if err != nil { + return isTable, err + } + wroteElem = wroteElem || !isTable + if wroteElem { + if i < rvlen-1 { + b.body = append(b.body, ',', ' ') + } else { + b.body = append(b.body, ']') + } + } + } + if !wroteElem { + b.body = b.body[:len(b.body)-1] // rub out '[' + } + b.arrayDepth-- + return !wroteElem, nil + case reflect.Struct: + child := b.newChild(name) + err := child.structFields(cfg, rv) + b.addChild(child) + return true, err + case reflect.Map: + child := b.newChild(name) + err := child.mapFields(cfg, rv) + b.addChild(child) + return true, err + default: + return false, fmt.Errorf("toml: marshal: unsupported type %v", rv.Kind()) + } + return false, nil +} + +func (b *tableBuf) marshaler(cfg *Config, rv reflect.Value, name string) (handled, isTable bool, err error) { + switch t := rv.Interface().(type) { + case encoding.TextMarshaler: + enc, err := t.MarshalText() + if err != nil { + return true, false, err + } + b.body = encodeTextMarshaler(b.body, string(enc)) + return true, false, nil + case MarshalerRec: + newval, err := t.MarshalTOML() + if err != nil { + return true, false, err + } + isTable, err = b.value(cfg, reflect.ValueOf(newval), name) + return true, isTable, err + case Marshaler: + enc, err := t.MarshalTOML() + if err != nil { + return true, false, err + } + b.body = append(b.body, enc...) + return true, false, nil + } + return false, false, nil +} + +func encodeTextMarshaler(buf []byte, v string) []byte { + // Emit the value without quotes if possible. + if v == "true" || v == "false" { + return append(buf, v...) + } else if _, err := time.Parse(time.RFC3339Nano, v); err == nil { + return append(buf, v...) + } else if _, err := strconv.ParseInt(v, 10, 64); err == nil { + return append(buf, v...) + } else if _, err := strconv.ParseUint(v, 10, 64); err == nil { + return append(buf, v...) + } else if _, err := strconv.ParseFloat(v, 64); err == nil { + return append(buf, v...) + } + return strconv.AppendQuote(buf, v) +} + +func encodeMapKey(rv reflect.Value) (string, error) { + if rv.Kind() == reflect.String { + return rv.String(), nil + } + if tm, ok := rv.Interface().(encoding.TextMarshaler); ok { + b, err := tm.MarshalText() + return string(b), err + } + switch rv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.FormatInt(rv.Int(), 10), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return strconv.FormatUint(rv.Uint(), 10), nil + } + return "", fmt.Errorf("toml: invalid map key type %v", rv.Type()) +} + +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array: + // encoding/json treats all arrays with non-zero length as non-empty. We check the + // array content here because zero-length arrays are almost never used. + len := v.Len() + for i := 0; i < len; i++ { + if !isEmptyValue(v.Index(i)) { + return false + } + } + return true + case reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func quoteName(s string) string { + if len(s) == 0 { + return strconv.Quote(s) + } + for _, r := range s { + if r >= '0' && r <= '9' || r >= 'A' && r <= 'Z' || r >= 'a' && r <= 'z' || r == '-' || r == '_' { + continue + } + return strconv.Quote(s) + } + return s +} diff --git a/vendor/github.com/naoina/toml/error.go b/vendor/github.com/naoina/toml/error.go new file mode 100644 index 00000000..cb73b5e0 --- /dev/null +++ b/vendor/github.com/naoina/toml/error.go @@ -0,0 +1,107 @@ +package toml + +import ( + "errors" + "fmt" + "reflect" + "strconv" +) + +var ( + errArrayMultiType = errors.New("array can't contain multiple types") +) + +// LineError is returned by Unmarshal, UnmarshalTable and Parse +// if the error is local to a line. +type LineError struct { + Line int + StructField string + Err error +} + +func (err *LineError) Error() string { + field := "" + if err.StructField != "" { + field = "(" + err.StructField + ") " + } + return fmt.Sprintf("line %d: %s%v", err.Line, field, err.Err) +} + +func lineError(line int, err error) error { + if err == nil { + return nil + } + if _, ok := err.(*LineError); ok { + return err + } + return &LineError{Line: line, Err: err} +} + +func lineErrorField(line int, field string, err error) error { + if lerr, ok := err.(*LineError); ok { + return lerr + } else if err != nil { + err = &LineError{Line: line, StructField: field, Err: err} + } + return err +} + +type overflowError struct { + kind reflect.Kind + v string +} + +func (err *overflowError) Error() string { + return fmt.Sprintf("value %s is out of range for %v", err.v, err.kind) +} + +func convertNumError(kind reflect.Kind, err error) error { + if numerr, ok := err.(*strconv.NumError); ok && numerr.Err == strconv.ErrRange { + return &overflowError{kind, numerr.Num} + } + return err +} + +type invalidUnmarshalError struct { + typ reflect.Type +} + +func (err *invalidUnmarshalError) Error() string { + if err.typ == nil { + return "toml: Unmarshal(nil)" + } + if err.typ.Kind() != reflect.Ptr { + return "toml: Unmarshal(non-pointer " + err.typ.String() + ")" + } + return "toml: Unmarshal(nil " + err.typ.String() + ")" +} + +type unmarshalTypeError struct { + what string + want string + typ reflect.Type +} + +func (err *unmarshalTypeError) Error() string { + msg := fmt.Sprintf("cannot unmarshal TOML %s into %s", err.what, err.typ) + if err.want != "" { + msg += " (need " + err.want + ")" + } + return msg +} + +type marshalNilError struct { + typ reflect.Type +} + +func (err *marshalNilError) Error() string { + return fmt.Sprintf("toml: cannot marshal nil %s", err.typ) +} + +type marshalTableError struct { + typ reflect.Type +} + +func (err *marshalTableError) Error() string { + return fmt.Sprintf("toml: cannot marshal %s as table, want struct or map type", err.typ) +} diff --git a/vendor/github.com/naoina/toml/parse.go b/vendor/github.com/naoina/toml/parse.go new file mode 100644 index 00000000..de910856 --- /dev/null +++ b/vendor/github.com/naoina/toml/parse.go @@ -0,0 +1,362 @@ +package toml + +import ( + "errors" + "fmt" + "strconv" + "strings" + + "github.com/naoina/toml/ast" +) + +// The parser is generated by github.com/pointlander/peg. To regenerate it, do: +// +// go get -u github.com/pointlander/peg +// go generate . + +//go:generate peg -switch -inline parse.peg + +var errParse = errors.New("invalid TOML syntax") + +// Parse returns an AST representation of TOML. +// The toplevel is represented by a table. +func Parse(data []byte) (*ast.Table, error) { + d := &parseState{p: &tomlParser{Buffer: string(data)}} + d.init() + + if err := d.parse(); err != nil { + return nil, err + } + + return d.p.toml.table, nil +} + +type parseState struct { + p *tomlParser +} + +func (d *parseState) init() { + d.p.Init() + d.p.toml.init(d.p.buffer) +} + +func (d *parseState) parse() error { + if err := d.p.Parse(); err != nil { + if err, ok := err.(*parseError); ok { + return lineError(err.Line(), errParse) + } + return err + } + return d.execute() +} + +func (d *parseState) execute() (err error) { + defer func() { + if e := recover(); e != nil { + lerr, ok := e.(*LineError) + if !ok { + panic(e) + } + err = lerr + } + }() + d.p.Execute() + return nil +} + +func (e *parseError) Line() int { + tokens := []token32{e.max} + positions, p := make([]int, 2*len(tokens)), 0 + for _, token := range tokens { + positions[p], p = int(token.begin), p+1 + positions[p], p = int(token.end), p+1 + } + for _, t := range translatePositions(e.p.buffer, positions) { + if e.p.line < t.line { + e.p.line = t.line + } + } + return e.p.line +} + +type stack struct { + key string + table *ast.Table +} + +type array struct { + parent *array + child *array + current *ast.Array + line int +} + +type toml struct { + table *ast.Table + line int + currentTable *ast.Table + s string + key string + tableKeys []string + val ast.Value + arr *array + stack []*stack + skip bool +} + +func (p *toml) init(data []rune) { + p.line = 1 + p.table = p.newTable(ast.TableTypeNormal, "") + p.table.Position.End = len(data) - 1 + p.table.Data = data[:len(data)-1] // truncate the end_symbol added by PEG parse generator. + p.currentTable = p.table +} + +func (p *toml) Error(err error) { + panic(lineError(p.line, err)) +} + +func (p *tomlParser) SetTime(begin, end int) { + p.val = &ast.Datetime{ + Position: ast.Position{Begin: begin, End: end}, + Data: p.buffer[begin:end], + Value: string(p.buffer[begin:end]), + } +} + +func (p *tomlParser) SetFloat64(begin, end int) { + p.val = &ast.Float{ + Position: ast.Position{Begin: begin, End: end}, + Data: p.buffer[begin:end], + Value: underscoreReplacer.Replace(string(p.buffer[begin:end])), + } +} + +func (p *tomlParser) SetInt64(begin, end int) { + p.val = &ast.Integer{ + Position: ast.Position{Begin: begin, End: end}, + Data: p.buffer[begin:end], + Value: underscoreReplacer.Replace(string(p.buffer[begin:end])), + } +} + +func (p *tomlParser) SetString(begin, end int) { + p.val = &ast.String{ + Position: ast.Position{Begin: begin, End: end}, + Data: p.buffer[begin:end], + Value: p.s, + } + p.s = "" +} + +func (p *tomlParser) SetBool(begin, end int) { + p.val = &ast.Boolean{ + Position: ast.Position{Begin: begin, End: end}, + Data: p.buffer[begin:end], + Value: string(p.buffer[begin:end]), + } +} + +func (p *tomlParser) StartArray() { + if p.arr == nil { + p.arr = &array{line: p.line, current: &ast.Array{}} + return + } + p.arr.child = &array{parent: p.arr, line: p.line, current: &ast.Array{}} + p.arr = p.arr.child +} + +func (p *tomlParser) AddArrayVal() { + if p.arr.current == nil { + p.arr.current = &ast.Array{} + } + p.arr.current.Value = append(p.arr.current.Value, p.val) +} + +func (p *tomlParser) SetArray(begin, end int) { + p.arr.current.Position = ast.Position{Begin: begin, End: end} + p.arr.current.Data = p.buffer[begin:end] + p.val = p.arr.current + p.arr = p.arr.parent +} + +func (p *toml) SetTable(buf []rune, begin, end int) { + rawName := string(buf[begin:end]) + p.setTable(p.table, rawName, p.tableKeys) + p.tableKeys = nil +} + +func (p *toml) setTable(parent *ast.Table, name string, names []string) { + parent, err := p.lookupTable(parent, names[:len(names)-1]) + if err != nil { + p.Error(err) + } + last := names[len(names)-1] + tbl := p.newTable(ast.TableTypeNormal, last) + switch v := parent.Fields[last].(type) { + case nil: + parent.Fields[last] = tbl + case []*ast.Table: + p.Error(fmt.Errorf("table `%s' is in conflict with array table in line %d", name, v[0].Line)) + case *ast.Table: + if (v.Position == ast.Position{}) { + // This table was created as an implicit parent. + // Replace it with the real defined table. + tbl.Fields = v.Fields + parent.Fields[last] = tbl + } else { + p.Error(fmt.Errorf("table `%s' is in conflict with table in line %d", name, v.Line)) + } + case *ast.KeyValue: + p.Error(fmt.Errorf("table `%s' is in conflict with line %d", name, v.Line)) + default: + p.Error(fmt.Errorf("BUG: table `%s' is in conflict but it's unknown type `%T'", last, v)) + } + p.currentTable = tbl +} + +func (p *toml) newTable(typ ast.TableType, name string) *ast.Table { + return &ast.Table{ + Line: p.line, + Name: name, + Type: typ, + Fields: make(map[string]interface{}), + } +} + +func (p *tomlParser) SetTableString(begin, end int) { + p.currentTable.Data = p.buffer[begin:end] + p.currentTable.Position.Begin = begin + p.currentTable.Position.End = end +} + +func (p *toml) SetArrayTable(buf []rune, begin, end int) { + rawName := string(buf[begin:end]) + p.setArrayTable(p.table, rawName, p.tableKeys) + p.tableKeys = nil +} + +func (p *toml) setArrayTable(parent *ast.Table, name string, names []string) { + parent, err := p.lookupTable(parent, names[:len(names)-1]) + if err != nil { + p.Error(err) + } + last := names[len(names)-1] + tbl := p.newTable(ast.TableTypeArray, last) + switch v := parent.Fields[last].(type) { + case nil: + parent.Fields[last] = []*ast.Table{tbl} + case []*ast.Table: + parent.Fields[last] = append(v, tbl) + case *ast.Table: + p.Error(fmt.Errorf("array table `%s' is in conflict with table in line %d", name, v.Line)) + case *ast.KeyValue: + p.Error(fmt.Errorf("array table `%s' is in conflict with line %d", name, v.Line)) + default: + p.Error(fmt.Errorf("BUG: array table `%s' is in conflict but it's unknown type `%T'", name, v)) + } + p.currentTable = tbl +} + +func (p *toml) StartInlineTable() { + p.skip = false + p.stack = append(p.stack, &stack{p.key, p.currentTable}) + names := []string{p.key} + if p.arr == nil { + p.setTable(p.currentTable, names[0], names) + } else { + p.setArrayTable(p.currentTable, names[0], names) + } +} + +func (p *toml) EndInlineTable() { + st := p.stack[len(p.stack)-1] + p.key, p.currentTable = st.key, st.table + p.stack[len(p.stack)-1] = nil + p.stack = p.stack[:len(p.stack)-1] + p.skip = true +} + +func (p *toml) AddLineCount(i int) { + p.line += i +} + +func (p *toml) SetKey(buf []rune, begin, end int) { + p.key = string(buf[begin:end]) + if len(p.key) > 0 && p.key[0] == '"' { + p.key = p.unquote(p.key) + } +} + +func (p *toml) AddTableKey() { + p.tableKeys = append(p.tableKeys, p.key) +} + +func (p *toml) AddKeyValue() { + if p.skip { + p.skip = false + return + } + if val, exists := p.currentTable.Fields[p.key]; exists { + switch v := val.(type) { + case *ast.Table: + p.Error(fmt.Errorf("key `%s' is in conflict with table in line %d", p.key, v.Line)) + case *ast.KeyValue: + p.Error(fmt.Errorf("key `%s' is in conflict with line %xd", p.key, v.Line)) + default: + p.Error(fmt.Errorf("BUG: key `%s' is in conflict but it's unknown type `%T'", p.key, v)) + } + } + p.currentTable.Fields[p.key] = &ast.KeyValue{Key: p.key, Value: p.val, Line: p.line} +} + +func (p *toml) SetBasicString(buf []rune, begin, end int) { + p.s = p.unquote(string(buf[begin:end])) +} + +func (p *toml) SetMultilineString() { + p.s = p.unquote(`"` + escapeReplacer.Replace(strings.TrimLeft(p.s, "\r\n")) + `"`) +} + +func (p *toml) AddMultilineBasicBody(buf []rune, begin, end int) { + p.s += string(buf[begin:end]) +} + +func (p *toml) SetLiteralString(buf []rune, begin, end int) { + p.s = string(buf[begin:end]) +} + +func (p *toml) SetMultilineLiteralString(buf []rune, begin, end int) { + p.s = strings.TrimLeft(string(buf[begin:end]), "\r\n") +} + +func (p *toml) unquote(s string) string { + s, err := strconv.Unquote(s) + if err != nil { + p.Error(err) + } + return s +} + +func (p *toml) lookupTable(t *ast.Table, keys []string) (*ast.Table, error) { + for _, s := range keys { + val, exists := t.Fields[s] + if !exists { + tbl := p.newTable(ast.TableTypeNormal, s) + t.Fields[s] = tbl + t = tbl + continue + } + switch v := val.(type) { + case *ast.Table: + t = v + case []*ast.Table: + t = v[len(v)-1] + case *ast.KeyValue: + return nil, fmt.Errorf("key `%s' is in conflict with line %d", s, v.Line) + default: + return nil, fmt.Errorf("BUG: key `%s' is in conflict but it's unknown type `%T'", s, v) + } + } + return t, nil +} diff --git a/vendor/github.com/naoina/toml/parse.peg b/vendor/github.com/naoina/toml/parse.peg new file mode 100644 index 00000000..dd9eb888 --- /dev/null +++ b/vendor/github.com/naoina/toml/parse.peg @@ -0,0 +1,147 @@ +package toml + +type tomlParser Peg { + toml +} + +TOML <- Expression (newline Expression)* newline? !. { _ = buffer } + +Expression <- ( + { p.SetTableString(begin, end) } + / ws keyval ws comment? + / ws comment? + / ws +) + +newline <- <[\r\n]+> { p.AddLineCount(end - begin) } + +ws <- [ \t]* +wsnl <- ( + [ \t] + / <[\r\n]> { p.AddLineCount(end - begin) } +)* + +comment <- '#' <[\t -\0x10FFFF]*> + +keyval <- key ws '=' ws val { p.AddKeyValue() } + +key <- bareKey / quotedKey + +bareKey <- <[0-9A-Za-z\-_]+> { p.SetKey(p.buffer, begin, end) } + +quotedKey <- < '"' basicChar* '"' > { p.SetKey(p.buffer, begin, end) } + +val <- ( + { p.SetTime(begin, end) } + / { p.SetFloat64(begin, end) } + / { p.SetInt64(begin, end) } + / { p.SetString(begin, end) } + / { p.SetBool(begin, end) } + / { p.SetArray(begin, end) } + / inlineTable +) + +table <- stdTable / arrayTable + +stdTable <- '[' ws ws ']' { p.SetTable(p.buffer, begin, end) } + +arrayTable <- '[[' ws ws ']]' { p.SetArrayTable(p.buffer, begin, end) } + +inlineTable <- ( + '{' { p.StartInlineTable() } + ws inlineTableKeyValues ws + '}' { p.EndInlineTable() } +) + +inlineTableKeyValues <- (keyval inlineTableValSep?)* + +tableKey <- tableKeyComp (tableKeySep tableKeyComp)* + +tableKeyComp <- key { p.AddTableKey() } + +tableKeySep <- ws '.' ws + +inlineTableValSep <- ws ',' ws + +integer <- [\-+]? int +int <- [1-9] (digit / '_' digit)+ / digit + +float <- integer (frac exp? / frac? exp) +frac <- '.' digit (digit / '_' digit)* +exp <- [eE] [\-+]? digit (digit / '_' digit)* + +string <- ( + mlLiteralString + / literalString + / mlBasicString + / basicString +) + +basicString <- <'"' basicChar* '"'> { p.SetBasicString(p.buffer, begin, end) } + +basicChar <- basicUnescaped / escaped +escaped <- escape ([btnfr"/\\] / 'u' hexQuad / 'U' hexQuad hexQuad) + +basicUnescaped <- [ -!#-\[\]-\0x10FFFF] + +escape <- '\\' + +mlBasicString <- '"""' mlBasicBody '"""' { p.SetMultilineString() } + +mlBasicBody <- ( + { p.AddMultilineBasicBody(p.buffer, begin, end) } + / escape newline wsnl +)* + +literalString <- "'" "'" { p.SetLiteralString(p.buffer, begin, end) } + +literalChar <- [\t -&(-\0x10FFFF] + +mlLiteralString <- "'''" "'''" { p.SetMultilineLiteralString(p.buffer, begin, end) } + +mlLiteralBody <- (!"'''" (mlLiteralChar / newline))* + +mlLiteralChar <- [\t -\0x10FFFF] + +hexdigit <- [0-9A-Fa-f] +hexQuad <- hexdigit hexdigit hexdigit hexdigit + +boolean <- 'true' / 'false' + +dateFullYear <- digitQuad +dateMonth <- digitDual +dateMDay <- digitDual +timeHour <- digitDual +timeMinute <- digitDual +timeSecond <- digitDual +timeSecfrac <- '.' digit+ +timeNumoffset <- [\-+] timeHour ':' timeMinute +timeOffset <- 'Z' / timeNumoffset +partialTime <- timeHour ':' timeMinute ':' timeSecond timeSecfrac? +fullDate <- dateFullYear '-' dateMonth '-' dateMDay +fullTime <- partialTime timeOffset +datetime <- (fullDate ('T' fullTime)?) / partialTime + +digit <- [0-9] +digitDual <- digit digit +digitQuad <- digitDual digitDual + +array <- ( + '[' { p.StartArray() } + wsnl arrayValues? wsnl + ']' +) + +arrayValues <- ( + val { p.AddArrayVal() } + ( + wsnl comment? + wsnl arraySep + wsnl comment? + wsnl val { p.AddArrayVal() } + )* + wsnl arraySep? + wsnl comment? +) + +arraySep <- ',' diff --git a/vendor/github.com/naoina/toml/parse.peg.go b/vendor/github.com/naoina/toml/parse.peg.go new file mode 100644 index 00000000..d768b00a --- /dev/null +++ b/vendor/github.com/naoina/toml/parse.peg.go @@ -0,0 +1,2579 @@ +package toml + +import ( + "fmt" + "math" + "sort" + "strconv" +) + +const endSymbol rune = 1114112 + +/* The rule types inferred from the grammar are below. */ +type pegRule uint8 + +const ( + ruleUnknown pegRule = iota + ruleTOML + ruleExpression + rulenewline + rulews + rulewsnl + rulecomment + rulekeyval + rulekey + rulebareKey + rulequotedKey + ruleval + ruletable + rulestdTable + rulearrayTable + ruleinlineTable + ruleinlineTableKeyValues + ruletableKey + ruletableKeyComp + ruletableKeySep + ruleinlineTableValSep + ruleinteger + ruleint + rulefloat + rulefrac + ruleexp + rulestring + rulebasicString + rulebasicChar + ruleescaped + rulebasicUnescaped + ruleescape + rulemlBasicString + rulemlBasicBody + ruleliteralString + ruleliteralChar + rulemlLiteralString + rulemlLiteralBody + rulemlLiteralChar + rulehexdigit + rulehexQuad + ruleboolean + ruledateFullYear + ruledateMonth + ruledateMDay + ruletimeHour + ruletimeMinute + ruletimeSecond + ruletimeSecfrac + ruletimeNumoffset + ruletimeOffset + rulepartialTime + rulefullDate + rulefullTime + ruledatetime + ruledigit + ruledigitDual + ruledigitQuad + rulearray + rulearrayValues + rulearraySep + ruleAction0 + rulePegText + ruleAction1 + ruleAction2 + ruleAction3 + ruleAction4 + ruleAction5 + ruleAction6 + ruleAction7 + ruleAction8 + ruleAction9 + ruleAction10 + ruleAction11 + ruleAction12 + ruleAction13 + ruleAction14 + ruleAction15 + ruleAction16 + ruleAction17 + ruleAction18 + ruleAction19 + ruleAction20 + ruleAction21 + ruleAction22 + ruleAction23 + ruleAction24 + ruleAction25 +) + +var rul3s = [...]string{ + "Unknown", + "TOML", + "Expression", + "newline", + "ws", + "wsnl", + "comment", + "keyval", + "key", + "bareKey", + "quotedKey", + "val", + "table", + "stdTable", + "arrayTable", + "inlineTable", + "inlineTableKeyValues", + "tableKey", + "tableKeyComp", + "tableKeySep", + "inlineTableValSep", + "integer", + "int", + "float", + "frac", + "exp", + "string", + "basicString", + "basicChar", + "escaped", + "basicUnescaped", + "escape", + "mlBasicString", + "mlBasicBody", + "literalString", + "literalChar", + "mlLiteralString", + "mlLiteralBody", + "mlLiteralChar", + "hexdigit", + "hexQuad", + "boolean", + "dateFullYear", + "dateMonth", + "dateMDay", + "timeHour", + "timeMinute", + "timeSecond", + "timeSecfrac", + "timeNumoffset", + "timeOffset", + "partialTime", + "fullDate", + "fullTime", + "datetime", + "digit", + "digitDual", + "digitQuad", + "array", + "arrayValues", + "arraySep", + "Action0", + "PegText", + "Action1", + "Action2", + "Action3", + "Action4", + "Action5", + "Action6", + "Action7", + "Action8", + "Action9", + "Action10", + "Action11", + "Action12", + "Action13", + "Action14", + "Action15", + "Action16", + "Action17", + "Action18", + "Action19", + "Action20", + "Action21", + "Action22", + "Action23", + "Action24", + "Action25", +} + +type token32 struct { + pegRule + begin, end uint32 +} + +func (t *token32) String() string { + return fmt.Sprintf("\x1B[34m%v\x1B[m %v %v", rul3s[t.pegRule], t.begin, t.end) +} + +type node32 struct { + token32 + up, next *node32 +} + +func (node *node32) print(pretty bool, buffer string) { + var print func(node *node32, depth int) + print = func(node *node32, depth int) { + for node != nil { + for c := 0; c < depth; c++ { + fmt.Printf(" ") + } + rule := rul3s[node.pegRule] + quote := strconv.Quote(string(([]rune(buffer)[node.begin:node.end]))) + if !pretty { + fmt.Printf("%v %v\n", rule, quote) + } else { + fmt.Printf("\x1B[34m%v\x1B[m %v\n", rule, quote) + } + if node.up != nil { + print(node.up, depth+1) + } + node = node.next + } + } + print(node, 0) +} + +func (node *node32) Print(buffer string) { + node.print(false, buffer) +} + +func (node *node32) PrettyPrint(buffer string) { + node.print(true, buffer) +} + +type tokens32 struct { + tree []token32 +} + +func (t *tokens32) Trim(length uint32) { + t.tree = t.tree[:length] +} + +func (t *tokens32) Print() { + for _, token := range t.tree { + fmt.Println(token.String()) + } +} + +func (t *tokens32) AST() *node32 { + type element struct { + node *node32 + down *element + } + tokens := t.Tokens() + var stack *element + for _, token := range tokens { + if token.begin == token.end { + continue + } + node := &node32{token32: token} + for stack != nil && stack.node.begin >= token.begin && stack.node.end <= token.end { + stack.node.next = node.up + node.up = stack.node + stack = stack.down + } + stack = &element{node: node, down: stack} + } + if stack != nil { + return stack.node + } + return nil +} + +func (t *tokens32) PrintSyntaxTree(buffer string) { + t.AST().Print(buffer) +} + +func (t *tokens32) PrettyPrintSyntaxTree(buffer string) { + t.AST().PrettyPrint(buffer) +} + +func (t *tokens32) Add(rule pegRule, begin, end, index uint32) { + if tree := t.tree; int(index) >= len(tree) { + expanded := make([]token32, 2*len(tree)) + copy(expanded, tree) + t.tree = expanded + } + t.tree[index] = token32{ + pegRule: rule, + begin: begin, + end: end, + } +} + +func (t *tokens32) Tokens() []token32 { + return t.tree +} + +type tomlParser struct { + toml + + Buffer string + buffer []rune + rules [88]func() bool + parse func(rule ...int) error + reset func() + Pretty bool + tokens32 +} + +func (p *tomlParser) Parse(rule ...int) error { + return p.parse(rule...) +} + +func (p *tomlParser) Reset() { + p.reset() +} + +type textPosition struct { + line, symbol int +} + +type textPositionMap map[int]textPosition + +func translatePositions(buffer []rune, positions []int) textPositionMap { + length, translations, j, line, symbol := len(positions), make(textPositionMap, len(positions)), 0, 1, 0 + sort.Ints(positions) + +search: + for i, c := range buffer { + if c == '\n' { + line, symbol = line+1, 0 + } else { + symbol++ + } + if i == positions[j] { + translations[positions[j]] = textPosition{line, symbol} + for j++; j < length; j++ { + if i != positions[j] { + continue search + } + } + break search + } + } + + return translations +} + +type parseError struct { + p *tomlParser + max token32 +} + +func (e *parseError) Error() string { + tokens, error := []token32{e.max}, "\n" + positions, p := make([]int, 2*len(tokens)), 0 + for _, token := range tokens { + positions[p], p = int(token.begin), p+1 + positions[p], p = int(token.end), p+1 + } + translations := translatePositions(e.p.buffer, positions) + format := "parse error near %v (line %v symbol %v - line %v symbol %v):\n%v\n" + if e.p.Pretty { + format = "parse error near \x1B[34m%v\x1B[m (line %v symbol %v - line %v symbol %v):\n%v\n" + } + for _, token := range tokens { + begin, end := int(token.begin), int(token.end) + error += fmt.Sprintf(format, + rul3s[token.pegRule], + translations[begin].line, translations[begin].symbol, + translations[end].line, translations[end].symbol, + strconv.Quote(string(e.p.buffer[begin:end]))) + } + + return error +} + +func (p *tomlParser) PrintSyntaxTree() { + if p.Pretty { + p.tokens32.PrettyPrintSyntaxTree(p.Buffer) + } else { + p.tokens32.PrintSyntaxTree(p.Buffer) + } +} + +func (p *tomlParser) Execute() { + buffer, _buffer, text, begin, end := p.Buffer, p.buffer, "", 0, 0 + for _, token := range p.Tokens() { + switch token.pegRule { + + case rulePegText: + begin, end = int(token.begin), int(token.end) + text = string(_buffer[begin:end]) + + case ruleAction0: + _ = buffer + case ruleAction1: + p.SetTableString(begin, end) + case ruleAction2: + p.AddLineCount(end - begin) + case ruleAction3: + p.AddLineCount(end - begin) + case ruleAction4: + p.AddKeyValue() + case ruleAction5: + p.SetKey(p.buffer, begin, end) + case ruleAction6: + p.SetKey(p.buffer, begin, end) + case ruleAction7: + p.SetTime(begin, end) + case ruleAction8: + p.SetFloat64(begin, end) + case ruleAction9: + p.SetInt64(begin, end) + case ruleAction10: + p.SetString(begin, end) + case ruleAction11: + p.SetBool(begin, end) + case ruleAction12: + p.SetArray(begin, end) + case ruleAction13: + p.SetTable(p.buffer, begin, end) + case ruleAction14: + p.SetArrayTable(p.buffer, begin, end) + case ruleAction15: + p.StartInlineTable() + case ruleAction16: + p.EndInlineTable() + case ruleAction17: + p.AddTableKey() + case ruleAction18: + p.SetBasicString(p.buffer, begin, end) + case ruleAction19: + p.SetMultilineString() + case ruleAction20: + p.AddMultilineBasicBody(p.buffer, begin, end) + case ruleAction21: + p.SetLiteralString(p.buffer, begin, end) + case ruleAction22: + p.SetMultilineLiteralString(p.buffer, begin, end) + case ruleAction23: + p.StartArray() + case ruleAction24: + p.AddArrayVal() + case ruleAction25: + p.AddArrayVal() + + } + } + _, _, _, _, _ = buffer, _buffer, text, begin, end +} + +func (p *tomlParser) Init() { + var ( + max token32 + position, tokenIndex uint32 + buffer []rune + ) + p.reset = func() { + max = token32{} + position, tokenIndex = 0, 0 + + p.buffer = []rune(p.Buffer) + if len(p.buffer) == 0 || p.buffer[len(p.buffer)-1] != endSymbol { + p.buffer = append(p.buffer, endSymbol) + } + buffer = p.buffer + } + p.reset() + + _rules := p.rules + tree := tokens32{tree: make([]token32, math.MaxInt16)} + p.parse = func(rule ...int) error { + r := 1 + if len(rule) > 0 { + r = rule[0] + } + matches := p.rules[r]() + p.tokens32 = tree + if matches { + p.Trim(tokenIndex) + return nil + } + return &parseError{p, max} + } + + add := func(rule pegRule, begin uint32) { + tree.Add(rule, begin, position, tokenIndex) + tokenIndex++ + if begin != position && position > max.end { + max = token32{rule, begin, position} + } + } + + matchDot := func() bool { + if buffer[position] != endSymbol { + position++ + return true + } + return false + } + + /*matchChar := func(c byte) bool { + if buffer[position] == c { + position++ + return true + } + return false + }*/ + + /*matchRange := func(lower byte, upper byte) bool { + if c := buffer[position]; c >= lower && c <= upper { + position++ + return true + } + return false + }*/ + + _rules = [...]func() bool{ + nil, + /* 0 TOML <- <(Expression (newline Expression)* newline? !. Action0)> */ + func() bool { + position0, tokenIndex0 := position, tokenIndex + { + position1 := position + if !_rules[ruleExpression]() { + goto l0 + } + l2: + { + position3, tokenIndex3 := position, tokenIndex + if !_rules[rulenewline]() { + goto l3 + } + if !_rules[ruleExpression]() { + goto l3 + } + goto l2 + l3: + position, tokenIndex = position3, tokenIndex3 + } + { + position4, tokenIndex4 := position, tokenIndex + if !_rules[rulenewline]() { + goto l4 + } + goto l5 + l4: + position, tokenIndex = position4, tokenIndex4 + } + l5: + { + position6, tokenIndex6 := position, tokenIndex + if !matchDot() { + goto l6 + } + goto l0 + l6: + position, tokenIndex = position6, tokenIndex6 + } + { + add(ruleAction0, position) + } + add(ruleTOML, position1) + } + return true + l0: + position, tokenIndex = position0, tokenIndex0 + return false + }, + /* 1 Expression <- <((<(ws table ws comment? (wsnl keyval ws comment?)*)> Action1) / (ws keyval ws comment?) / (ws comment?) / ws)> */ + func() bool { + position8, tokenIndex8 := position, tokenIndex + { + position9 := position + { + position10, tokenIndex10 := position, tokenIndex + { + position12 := position + if !_rules[rulews]() { + goto l11 + } + { + position13 := position + { + position14, tokenIndex14 := position, tokenIndex + { + position16 := position + if buffer[position] != rune('[') { + goto l15 + } + position++ + if !_rules[rulews]() { + goto l15 + } + { + position17 := position + if !_rules[ruletableKey]() { + goto l15 + } + add(rulePegText, position17) + } + if !_rules[rulews]() { + goto l15 + } + if buffer[position] != rune(']') { + goto l15 + } + position++ + { + add(ruleAction13, position) + } + add(rulestdTable, position16) + } + goto l14 + l15: + position, tokenIndex = position14, tokenIndex14 + { + position19 := position + if buffer[position] != rune('[') { + goto l11 + } + position++ + if buffer[position] != rune('[') { + goto l11 + } + position++ + if !_rules[rulews]() { + goto l11 + } + { + position20 := position + if !_rules[ruletableKey]() { + goto l11 + } + add(rulePegText, position20) + } + if !_rules[rulews]() { + goto l11 + } + if buffer[position] != rune(']') { + goto l11 + } + position++ + if buffer[position] != rune(']') { + goto l11 + } + position++ + { + add(ruleAction14, position) + } + add(rulearrayTable, position19) + } + } + l14: + add(ruletable, position13) + } + if !_rules[rulews]() { + goto l11 + } + { + position22, tokenIndex22 := position, tokenIndex + if !_rules[rulecomment]() { + goto l22 + } + goto l23 + l22: + position, tokenIndex = position22, tokenIndex22 + } + l23: + l24: + { + position25, tokenIndex25 := position, tokenIndex + if !_rules[rulewsnl]() { + goto l25 + } + if !_rules[rulekeyval]() { + goto l25 + } + if !_rules[rulews]() { + goto l25 + } + { + position26, tokenIndex26 := position, tokenIndex + if !_rules[rulecomment]() { + goto l26 + } + goto l27 + l26: + position, tokenIndex = position26, tokenIndex26 + } + l27: + goto l24 + l25: + position, tokenIndex = position25, tokenIndex25 + } + add(rulePegText, position12) + } + { + add(ruleAction1, position) + } + goto l10 + l11: + position, tokenIndex = position10, tokenIndex10 + if !_rules[rulews]() { + goto l29 + } + if !_rules[rulekeyval]() { + goto l29 + } + if !_rules[rulews]() { + goto l29 + } + { + position30, tokenIndex30 := position, tokenIndex + if !_rules[rulecomment]() { + goto l30 + } + goto l31 + l30: + position, tokenIndex = position30, tokenIndex30 + } + l31: + goto l10 + l29: + position, tokenIndex = position10, tokenIndex10 + if !_rules[rulews]() { + goto l32 + } + { + position33, tokenIndex33 := position, tokenIndex + if !_rules[rulecomment]() { + goto l33 + } + goto l34 + l33: + position, tokenIndex = position33, tokenIndex33 + } + l34: + goto l10 + l32: + position, tokenIndex = position10, tokenIndex10 + if !_rules[rulews]() { + goto l8 + } + } + l10: + add(ruleExpression, position9) + } + return true + l8: + position, tokenIndex = position8, tokenIndex8 + return false + }, + /* 2 newline <- <(<('\r' / '\n')+> Action2)> */ + func() bool { + position35, tokenIndex35 := position, tokenIndex + { + position36 := position + { + position37 := position + { + position40, tokenIndex40 := position, tokenIndex + if buffer[position] != rune('\r') { + goto l41 + } + position++ + goto l40 + l41: + position, tokenIndex = position40, tokenIndex40 + if buffer[position] != rune('\n') { + goto l35 + } + position++ + } + l40: + l38: + { + position39, tokenIndex39 := position, tokenIndex + { + position42, tokenIndex42 := position, tokenIndex + if buffer[position] != rune('\r') { + goto l43 + } + position++ + goto l42 + l43: + position, tokenIndex = position42, tokenIndex42 + if buffer[position] != rune('\n') { + goto l39 + } + position++ + } + l42: + goto l38 + l39: + position, tokenIndex = position39, tokenIndex39 + } + add(rulePegText, position37) + } + { + add(ruleAction2, position) + } + add(rulenewline, position36) + } + return true + l35: + position, tokenIndex = position35, tokenIndex35 + return false + }, + /* 3 ws <- <(' ' / '\t')*> */ + func() bool { + { + position46 := position + l47: + { + position48, tokenIndex48 := position, tokenIndex + { + position49, tokenIndex49 := position, tokenIndex + if buffer[position] != rune(' ') { + goto l50 + } + position++ + goto l49 + l50: + position, tokenIndex = position49, tokenIndex49 + if buffer[position] != rune('\t') { + goto l48 + } + position++ + } + l49: + goto l47 + l48: + position, tokenIndex = position48, tokenIndex48 + } + add(rulews, position46) + } + return true + }, + /* 4 wsnl <- <((&('\t') '\t') | (&(' ') ' ') | (&('\n' | '\r') (<('\r' / '\n')> Action3)))*> */ + func() bool { + { + position52 := position + l53: + { + position54, tokenIndex54 := position, tokenIndex + { + switch buffer[position] { + case '\t': + if buffer[position] != rune('\t') { + goto l54 + } + position++ + break + case ' ': + if buffer[position] != rune(' ') { + goto l54 + } + position++ + break + default: + { + position56 := position + { + position57, tokenIndex57 := position, tokenIndex + if buffer[position] != rune('\r') { + goto l58 + } + position++ + goto l57 + l58: + position, tokenIndex = position57, tokenIndex57 + if buffer[position] != rune('\n') { + goto l54 + } + position++ + } + l57: + add(rulePegText, position56) + } + { + add(ruleAction3, position) + } + break + } + } + + goto l53 + l54: + position, tokenIndex = position54, tokenIndex54 + } + add(rulewsnl, position52) + } + return true + }, + /* 5 comment <- <('#' <('\t' / [ -\U0010ffff])*>)> */ + func() bool { + position60, tokenIndex60 := position, tokenIndex + { + position61 := position + if buffer[position] != rune('#') { + goto l60 + } + position++ + { + position62 := position + l63: + { + position64, tokenIndex64 := position, tokenIndex + { + position65, tokenIndex65 := position, tokenIndex + if buffer[position] != rune('\t') { + goto l66 + } + position++ + goto l65 + l66: + position, tokenIndex = position65, tokenIndex65 + if c := buffer[position]; c < rune(' ') || c > rune('\U0010ffff') { + goto l64 + } + position++ + } + l65: + goto l63 + l64: + position, tokenIndex = position64, tokenIndex64 + } + add(rulePegText, position62) + } + add(rulecomment, position61) + } + return true + l60: + position, tokenIndex = position60, tokenIndex60 + return false + }, + /* 6 keyval <- <(key ws '=' ws val Action4)> */ + func() bool { + position67, tokenIndex67 := position, tokenIndex + { + position68 := position + if !_rules[rulekey]() { + goto l67 + } + if !_rules[rulews]() { + goto l67 + } + if buffer[position] != rune('=') { + goto l67 + } + position++ + if !_rules[rulews]() { + goto l67 + } + if !_rules[ruleval]() { + goto l67 + } + { + add(ruleAction4, position) + } + add(rulekeyval, position68) + } + return true + l67: + position, tokenIndex = position67, tokenIndex67 + return false + }, + /* 7 key <- <(bareKey / quotedKey)> */ + func() bool { + position70, tokenIndex70 := position, tokenIndex + { + position71 := position + { + position72, tokenIndex72 := position, tokenIndex + { + position74 := position + { + position75 := position + { + switch buffer[position] { + case '_': + if buffer[position] != rune('_') { + goto l73 + } + position++ + break + case '-': + if buffer[position] != rune('-') { + goto l73 + } + position++ + break + case 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z': + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l73 + } + position++ + break + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l73 + } + position++ + break + default: + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l73 + } + position++ + break + } + } + + l76: + { + position77, tokenIndex77 := position, tokenIndex + { + switch buffer[position] { + case '_': + if buffer[position] != rune('_') { + goto l77 + } + position++ + break + case '-': + if buffer[position] != rune('-') { + goto l77 + } + position++ + break + case 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z': + if c := buffer[position]; c < rune('a') || c > rune('z') { + goto l77 + } + position++ + break + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l77 + } + position++ + break + default: + if c := buffer[position]; c < rune('A') || c > rune('Z') { + goto l77 + } + position++ + break + } + } + + goto l76 + l77: + position, tokenIndex = position77, tokenIndex77 + } + add(rulePegText, position75) + } + { + add(ruleAction5, position) + } + add(rulebareKey, position74) + } + goto l72 + l73: + position, tokenIndex = position72, tokenIndex72 + { + position81 := position + { + position82 := position + if buffer[position] != rune('"') { + goto l70 + } + position++ + l83: + { + position84, tokenIndex84 := position, tokenIndex + if !_rules[rulebasicChar]() { + goto l84 + } + goto l83 + l84: + position, tokenIndex = position84, tokenIndex84 + } + if buffer[position] != rune('"') { + goto l70 + } + position++ + add(rulePegText, position82) + } + { + add(ruleAction6, position) + } + add(rulequotedKey, position81) + } + } + l72: + add(rulekey, position71) + } + return true + l70: + position, tokenIndex = position70, tokenIndex70 + return false + }, + /* 8 bareKey <- <(<((&('_') '_') | (&('-') '-') | (&('a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z') [a-z]) | (&('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') [0-9]) | (&('A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z') [A-Z]))+> Action5)> */ + nil, + /* 9 quotedKey <- <(<('"' basicChar* '"')> Action6)> */ + nil, + /* 10 val <- <(( Action7) / ( Action8) / ((&('{') inlineTable) | (&('[') ( Action12)) | (&('f' | 't') ( Action11)) | (&('"' | '\'') ( Action10)) | (&('+' | '-' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') ( Action9))))> */ + func() bool { + position88, tokenIndex88 := position, tokenIndex + { + position89 := position + { + position90, tokenIndex90 := position, tokenIndex + { + position92 := position + { + position93 := position + { + position94, tokenIndex94 := position, tokenIndex + { + position96 := position + { + position97 := position + { + position98 := position + if !_rules[ruledigitDual]() { + goto l95 + } + if !_rules[ruledigitDual]() { + goto l95 + } + add(ruledigitQuad, position98) + } + add(ruledateFullYear, position97) + } + if buffer[position] != rune('-') { + goto l95 + } + position++ + { + position99 := position + if !_rules[ruledigitDual]() { + goto l95 + } + add(ruledateMonth, position99) + } + if buffer[position] != rune('-') { + goto l95 + } + position++ + { + position100 := position + if !_rules[ruledigitDual]() { + goto l95 + } + add(ruledateMDay, position100) + } + add(rulefullDate, position96) + } + { + position101, tokenIndex101 := position, tokenIndex + if buffer[position] != rune('T') { + goto l101 + } + position++ + { + position103 := position + if !_rules[rulepartialTime]() { + goto l101 + } + { + position104 := position + { + position105, tokenIndex105 := position, tokenIndex + if buffer[position] != rune('Z') { + goto l106 + } + position++ + goto l105 + l106: + position, tokenIndex = position105, tokenIndex105 + { + position107 := position + { + position108, tokenIndex108 := position, tokenIndex + if buffer[position] != rune('-') { + goto l109 + } + position++ + goto l108 + l109: + position, tokenIndex = position108, tokenIndex108 + if buffer[position] != rune('+') { + goto l101 + } + position++ + } + l108: + if !_rules[ruletimeHour]() { + goto l101 + } + if buffer[position] != rune(':') { + goto l101 + } + position++ + if !_rules[ruletimeMinute]() { + goto l101 + } + add(ruletimeNumoffset, position107) + } + } + l105: + add(ruletimeOffset, position104) + } + add(rulefullTime, position103) + } + goto l102 + l101: + position, tokenIndex = position101, tokenIndex101 + } + l102: + goto l94 + l95: + position, tokenIndex = position94, tokenIndex94 + if !_rules[rulepartialTime]() { + goto l91 + } + } + l94: + add(ruledatetime, position93) + } + add(rulePegText, position92) + } + { + add(ruleAction7, position) + } + goto l90 + l91: + position, tokenIndex = position90, tokenIndex90 + { + position112 := position + { + position113 := position + if !_rules[ruleinteger]() { + goto l111 + } + { + position114, tokenIndex114 := position, tokenIndex + if !_rules[rulefrac]() { + goto l115 + } + { + position116, tokenIndex116 := position, tokenIndex + if !_rules[ruleexp]() { + goto l116 + } + goto l117 + l116: + position, tokenIndex = position116, tokenIndex116 + } + l117: + goto l114 + l115: + position, tokenIndex = position114, tokenIndex114 + { + position118, tokenIndex118 := position, tokenIndex + if !_rules[rulefrac]() { + goto l118 + } + goto l119 + l118: + position, tokenIndex = position118, tokenIndex118 + } + l119: + if !_rules[ruleexp]() { + goto l111 + } + } + l114: + add(rulefloat, position113) + } + add(rulePegText, position112) + } + { + add(ruleAction8, position) + } + goto l90 + l111: + position, tokenIndex = position90, tokenIndex90 + { + switch buffer[position] { + case '{': + { + position122 := position + if buffer[position] != rune('{') { + goto l88 + } + position++ + { + add(ruleAction15, position) + } + if !_rules[rulews]() { + goto l88 + } + { + position124 := position + l125: + { + position126, tokenIndex126 := position, tokenIndex + if !_rules[rulekeyval]() { + goto l126 + } + { + position127, tokenIndex127 := position, tokenIndex + { + position129 := position + if !_rules[rulews]() { + goto l127 + } + if buffer[position] != rune(',') { + goto l127 + } + position++ + if !_rules[rulews]() { + goto l127 + } + add(ruleinlineTableValSep, position129) + } + goto l128 + l127: + position, tokenIndex = position127, tokenIndex127 + } + l128: + goto l125 + l126: + position, tokenIndex = position126, tokenIndex126 + } + add(ruleinlineTableKeyValues, position124) + } + if !_rules[rulews]() { + goto l88 + } + if buffer[position] != rune('}') { + goto l88 + } + position++ + { + add(ruleAction16, position) + } + add(ruleinlineTable, position122) + } + break + case '[': + { + position131 := position + { + position132 := position + if buffer[position] != rune('[') { + goto l88 + } + position++ + { + add(ruleAction23, position) + } + if !_rules[rulewsnl]() { + goto l88 + } + { + position134, tokenIndex134 := position, tokenIndex + { + position136 := position + if !_rules[ruleval]() { + goto l134 + } + { + add(ruleAction24, position) + } + l138: + { + position139, tokenIndex139 := position, tokenIndex + if !_rules[rulewsnl]() { + goto l139 + } + { + position140, tokenIndex140 := position, tokenIndex + if !_rules[rulecomment]() { + goto l140 + } + goto l141 + l140: + position, tokenIndex = position140, tokenIndex140 + } + l141: + if !_rules[rulewsnl]() { + goto l139 + } + if !_rules[rulearraySep]() { + goto l139 + } + if !_rules[rulewsnl]() { + goto l139 + } + { + position142, tokenIndex142 := position, tokenIndex + if !_rules[rulecomment]() { + goto l142 + } + goto l143 + l142: + position, tokenIndex = position142, tokenIndex142 + } + l143: + if !_rules[rulewsnl]() { + goto l139 + } + if !_rules[ruleval]() { + goto l139 + } + { + add(ruleAction25, position) + } + goto l138 + l139: + position, tokenIndex = position139, tokenIndex139 + } + if !_rules[rulewsnl]() { + goto l134 + } + { + position145, tokenIndex145 := position, tokenIndex + if !_rules[rulearraySep]() { + goto l145 + } + goto l146 + l145: + position, tokenIndex = position145, tokenIndex145 + } + l146: + if !_rules[rulewsnl]() { + goto l134 + } + { + position147, tokenIndex147 := position, tokenIndex + if !_rules[rulecomment]() { + goto l147 + } + goto l148 + l147: + position, tokenIndex = position147, tokenIndex147 + } + l148: + add(rulearrayValues, position136) + } + goto l135 + l134: + position, tokenIndex = position134, tokenIndex134 + } + l135: + if !_rules[rulewsnl]() { + goto l88 + } + if buffer[position] != rune(']') { + goto l88 + } + position++ + add(rulearray, position132) + } + add(rulePegText, position131) + } + { + add(ruleAction12, position) + } + break + case 'f', 't': + { + position150 := position + { + position151 := position + { + position152, tokenIndex152 := position, tokenIndex + if buffer[position] != rune('t') { + goto l153 + } + position++ + if buffer[position] != rune('r') { + goto l153 + } + position++ + if buffer[position] != rune('u') { + goto l153 + } + position++ + if buffer[position] != rune('e') { + goto l153 + } + position++ + goto l152 + l153: + position, tokenIndex = position152, tokenIndex152 + if buffer[position] != rune('f') { + goto l88 + } + position++ + if buffer[position] != rune('a') { + goto l88 + } + position++ + if buffer[position] != rune('l') { + goto l88 + } + position++ + if buffer[position] != rune('s') { + goto l88 + } + position++ + if buffer[position] != rune('e') { + goto l88 + } + position++ + } + l152: + add(ruleboolean, position151) + } + add(rulePegText, position150) + } + { + add(ruleAction11, position) + } + break + case '"', '\'': + { + position155 := position + { + position156 := position + { + position157, tokenIndex157 := position, tokenIndex + { + position159 := position + if buffer[position] != rune('\'') { + goto l158 + } + position++ + if buffer[position] != rune('\'') { + goto l158 + } + position++ + if buffer[position] != rune('\'') { + goto l158 + } + position++ + { + position160 := position + { + position161 := position + l162: + { + position163, tokenIndex163 := position, tokenIndex + { + position164, tokenIndex164 := position, tokenIndex + if buffer[position] != rune('\'') { + goto l164 + } + position++ + if buffer[position] != rune('\'') { + goto l164 + } + position++ + if buffer[position] != rune('\'') { + goto l164 + } + position++ + goto l163 + l164: + position, tokenIndex = position164, tokenIndex164 + } + { + position165, tokenIndex165 := position, tokenIndex + { + position167 := position + { + position168, tokenIndex168 := position, tokenIndex + if buffer[position] != rune('\t') { + goto l169 + } + position++ + goto l168 + l169: + position, tokenIndex = position168, tokenIndex168 + if c := buffer[position]; c < rune(' ') || c > rune('\U0010ffff') { + goto l166 + } + position++ + } + l168: + add(rulemlLiteralChar, position167) + } + goto l165 + l166: + position, tokenIndex = position165, tokenIndex165 + if !_rules[rulenewline]() { + goto l163 + } + } + l165: + goto l162 + l163: + position, tokenIndex = position163, tokenIndex163 + } + add(rulemlLiteralBody, position161) + } + add(rulePegText, position160) + } + if buffer[position] != rune('\'') { + goto l158 + } + position++ + if buffer[position] != rune('\'') { + goto l158 + } + position++ + if buffer[position] != rune('\'') { + goto l158 + } + position++ + { + add(ruleAction22, position) + } + add(rulemlLiteralString, position159) + } + goto l157 + l158: + position, tokenIndex = position157, tokenIndex157 + { + position172 := position + if buffer[position] != rune('\'') { + goto l171 + } + position++ + { + position173 := position + l174: + { + position175, tokenIndex175 := position, tokenIndex + { + position176 := position + { + switch buffer[position] { + case '\t': + if buffer[position] != rune('\t') { + goto l175 + } + position++ + break + case ' ', '!', '"', '#', '$', '%', '&': + if c := buffer[position]; c < rune(' ') || c > rune('&') { + goto l175 + } + position++ + break + default: + if c := buffer[position]; c < rune('(') || c > rune('\U0010ffff') { + goto l175 + } + position++ + break + } + } + + add(ruleliteralChar, position176) + } + goto l174 + l175: + position, tokenIndex = position175, tokenIndex175 + } + add(rulePegText, position173) + } + if buffer[position] != rune('\'') { + goto l171 + } + position++ + { + add(ruleAction21, position) + } + add(ruleliteralString, position172) + } + goto l157 + l171: + position, tokenIndex = position157, tokenIndex157 + { + position180 := position + if buffer[position] != rune('"') { + goto l179 + } + position++ + if buffer[position] != rune('"') { + goto l179 + } + position++ + if buffer[position] != rune('"') { + goto l179 + } + position++ + { + position181 := position + l182: + { + position183, tokenIndex183 := position, tokenIndex + { + position184, tokenIndex184 := position, tokenIndex + { + position186 := position + { + position187, tokenIndex187 := position, tokenIndex + if !_rules[rulebasicChar]() { + goto l188 + } + goto l187 + l188: + position, tokenIndex = position187, tokenIndex187 + if !_rules[rulenewline]() { + goto l185 + } + } + l187: + add(rulePegText, position186) + } + { + add(ruleAction20, position) + } + goto l184 + l185: + position, tokenIndex = position184, tokenIndex184 + if !_rules[ruleescape]() { + goto l183 + } + if !_rules[rulenewline]() { + goto l183 + } + if !_rules[rulewsnl]() { + goto l183 + } + } + l184: + goto l182 + l183: + position, tokenIndex = position183, tokenIndex183 + } + add(rulemlBasicBody, position181) + } + if buffer[position] != rune('"') { + goto l179 + } + position++ + if buffer[position] != rune('"') { + goto l179 + } + position++ + if buffer[position] != rune('"') { + goto l179 + } + position++ + { + add(ruleAction19, position) + } + add(rulemlBasicString, position180) + } + goto l157 + l179: + position, tokenIndex = position157, tokenIndex157 + { + position191 := position + { + position192 := position + if buffer[position] != rune('"') { + goto l88 + } + position++ + l193: + { + position194, tokenIndex194 := position, tokenIndex + if !_rules[rulebasicChar]() { + goto l194 + } + goto l193 + l194: + position, tokenIndex = position194, tokenIndex194 + } + if buffer[position] != rune('"') { + goto l88 + } + position++ + add(rulePegText, position192) + } + { + add(ruleAction18, position) + } + add(rulebasicString, position191) + } + } + l157: + add(rulestring, position156) + } + add(rulePegText, position155) + } + { + add(ruleAction10, position) + } + break + default: + { + position197 := position + if !_rules[ruleinteger]() { + goto l88 + } + add(rulePegText, position197) + } + { + add(ruleAction9, position) + } + break + } + } + + } + l90: + add(ruleval, position89) + } + return true + l88: + position, tokenIndex = position88, tokenIndex88 + return false + }, + /* 11 table <- <(stdTable / arrayTable)> */ + nil, + /* 12 stdTable <- <('[' ws ws ']' Action13)> */ + nil, + /* 13 arrayTable <- <('[' '[' ws ws (']' ']') Action14)> */ + nil, + /* 14 inlineTable <- <('{' Action15 ws inlineTableKeyValues ws '}' Action16)> */ + nil, + /* 15 inlineTableKeyValues <- <(keyval inlineTableValSep?)*> */ + nil, + /* 16 tableKey <- <(tableKeyComp (tableKeySep tableKeyComp)*)> */ + func() bool { + position204, tokenIndex204 := position, tokenIndex + { + position205 := position + if !_rules[ruletableKeyComp]() { + goto l204 + } + l206: + { + position207, tokenIndex207 := position, tokenIndex + { + position208 := position + if !_rules[rulews]() { + goto l207 + } + if buffer[position] != rune('.') { + goto l207 + } + position++ + if !_rules[rulews]() { + goto l207 + } + add(ruletableKeySep, position208) + } + if !_rules[ruletableKeyComp]() { + goto l207 + } + goto l206 + l207: + position, tokenIndex = position207, tokenIndex207 + } + add(ruletableKey, position205) + } + return true + l204: + position, tokenIndex = position204, tokenIndex204 + return false + }, + /* 17 tableKeyComp <- <(key Action17)> */ + func() bool { + position209, tokenIndex209 := position, tokenIndex + { + position210 := position + if !_rules[rulekey]() { + goto l209 + } + { + add(ruleAction17, position) + } + add(ruletableKeyComp, position210) + } + return true + l209: + position, tokenIndex = position209, tokenIndex209 + return false + }, + /* 18 tableKeySep <- <(ws '.' ws)> */ + nil, + /* 19 inlineTableValSep <- <(ws ',' ws)> */ + nil, + /* 20 integer <- <(('-' / '+')? int)> */ + func() bool { + position214, tokenIndex214 := position, tokenIndex + { + position215 := position + { + position216, tokenIndex216 := position, tokenIndex + { + position218, tokenIndex218 := position, tokenIndex + if buffer[position] != rune('-') { + goto l219 + } + position++ + goto l218 + l219: + position, tokenIndex = position218, tokenIndex218 + if buffer[position] != rune('+') { + goto l216 + } + position++ + } + l218: + goto l217 + l216: + position, tokenIndex = position216, tokenIndex216 + } + l217: + { + position220 := position + { + position221, tokenIndex221 := position, tokenIndex + if c := buffer[position]; c < rune('1') || c > rune('9') { + goto l222 + } + position++ + { + position225, tokenIndex225 := position, tokenIndex + if !_rules[ruledigit]() { + goto l226 + } + goto l225 + l226: + position, tokenIndex = position225, tokenIndex225 + if buffer[position] != rune('_') { + goto l222 + } + position++ + if !_rules[ruledigit]() { + goto l222 + } + } + l225: + l223: + { + position224, tokenIndex224 := position, tokenIndex + { + position227, tokenIndex227 := position, tokenIndex + if !_rules[ruledigit]() { + goto l228 + } + goto l227 + l228: + position, tokenIndex = position227, tokenIndex227 + if buffer[position] != rune('_') { + goto l224 + } + position++ + if !_rules[ruledigit]() { + goto l224 + } + } + l227: + goto l223 + l224: + position, tokenIndex = position224, tokenIndex224 + } + goto l221 + l222: + position, tokenIndex = position221, tokenIndex221 + if !_rules[ruledigit]() { + goto l214 + } + } + l221: + add(ruleint, position220) + } + add(ruleinteger, position215) + } + return true + l214: + position, tokenIndex = position214, tokenIndex214 + return false + }, + /* 21 int <- <(([1-9] (digit / ('_' digit))+) / digit)> */ + nil, + /* 22 float <- <(integer ((frac exp?) / (frac? exp)))> */ + nil, + /* 23 frac <- <('.' digit (digit / ('_' digit))*)> */ + func() bool { + position231, tokenIndex231 := position, tokenIndex + { + position232 := position + if buffer[position] != rune('.') { + goto l231 + } + position++ + if !_rules[ruledigit]() { + goto l231 + } + l233: + { + position234, tokenIndex234 := position, tokenIndex + { + position235, tokenIndex235 := position, tokenIndex + if !_rules[ruledigit]() { + goto l236 + } + goto l235 + l236: + position, tokenIndex = position235, tokenIndex235 + if buffer[position] != rune('_') { + goto l234 + } + position++ + if !_rules[ruledigit]() { + goto l234 + } + } + l235: + goto l233 + l234: + position, tokenIndex = position234, tokenIndex234 + } + add(rulefrac, position232) + } + return true + l231: + position, tokenIndex = position231, tokenIndex231 + return false + }, + /* 24 exp <- <(('e' / 'E') ('-' / '+')? digit (digit / ('_' digit))*)> */ + func() bool { + position237, tokenIndex237 := position, tokenIndex + { + position238 := position + { + position239, tokenIndex239 := position, tokenIndex + if buffer[position] != rune('e') { + goto l240 + } + position++ + goto l239 + l240: + position, tokenIndex = position239, tokenIndex239 + if buffer[position] != rune('E') { + goto l237 + } + position++ + } + l239: + { + position241, tokenIndex241 := position, tokenIndex + { + position243, tokenIndex243 := position, tokenIndex + if buffer[position] != rune('-') { + goto l244 + } + position++ + goto l243 + l244: + position, tokenIndex = position243, tokenIndex243 + if buffer[position] != rune('+') { + goto l241 + } + position++ + } + l243: + goto l242 + l241: + position, tokenIndex = position241, tokenIndex241 + } + l242: + if !_rules[ruledigit]() { + goto l237 + } + l245: + { + position246, tokenIndex246 := position, tokenIndex + { + position247, tokenIndex247 := position, tokenIndex + if !_rules[ruledigit]() { + goto l248 + } + goto l247 + l248: + position, tokenIndex = position247, tokenIndex247 + if buffer[position] != rune('_') { + goto l246 + } + position++ + if !_rules[ruledigit]() { + goto l246 + } + } + l247: + goto l245 + l246: + position, tokenIndex = position246, tokenIndex246 + } + add(ruleexp, position238) + } + return true + l237: + position, tokenIndex = position237, tokenIndex237 + return false + }, + /* 25 string <- <(mlLiteralString / literalString / mlBasicString / basicString)> */ + nil, + /* 26 basicString <- <(<('"' basicChar* '"')> Action18)> */ + nil, + /* 27 basicChar <- <(basicUnescaped / escaped)> */ + func() bool { + position251, tokenIndex251 := position, tokenIndex + { + position252 := position + { + position253, tokenIndex253 := position, tokenIndex + { + position255 := position + { + switch buffer[position] { + case ' ', '!': + if c := buffer[position]; c < rune(' ') || c > rune('!') { + goto l254 + } + position++ + break + case '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[': + if c := buffer[position]; c < rune('#') || c > rune('[') { + goto l254 + } + position++ + break + default: + if c := buffer[position]; c < rune(']') || c > rune('\U0010ffff') { + goto l254 + } + position++ + break + } + } + + add(rulebasicUnescaped, position255) + } + goto l253 + l254: + position, tokenIndex = position253, tokenIndex253 + { + position257 := position + if !_rules[ruleescape]() { + goto l251 + } + { + switch buffer[position] { + case 'U': + if buffer[position] != rune('U') { + goto l251 + } + position++ + if !_rules[rulehexQuad]() { + goto l251 + } + if !_rules[rulehexQuad]() { + goto l251 + } + break + case 'u': + if buffer[position] != rune('u') { + goto l251 + } + position++ + if !_rules[rulehexQuad]() { + goto l251 + } + break + case '\\': + if buffer[position] != rune('\\') { + goto l251 + } + position++ + break + case '/': + if buffer[position] != rune('/') { + goto l251 + } + position++ + break + case '"': + if buffer[position] != rune('"') { + goto l251 + } + position++ + break + case 'r': + if buffer[position] != rune('r') { + goto l251 + } + position++ + break + case 'f': + if buffer[position] != rune('f') { + goto l251 + } + position++ + break + case 'n': + if buffer[position] != rune('n') { + goto l251 + } + position++ + break + case 't': + if buffer[position] != rune('t') { + goto l251 + } + position++ + break + default: + if buffer[position] != rune('b') { + goto l251 + } + position++ + break + } + } + + add(ruleescaped, position257) + } + } + l253: + add(rulebasicChar, position252) + } + return true + l251: + position, tokenIndex = position251, tokenIndex251 + return false + }, + /* 28 escaped <- <(escape ((&('U') ('U' hexQuad hexQuad)) | (&('u') ('u' hexQuad)) | (&('\\') '\\') | (&('/') '/') | (&('"') '"') | (&('r') 'r') | (&('f') 'f') | (&('n') 'n') | (&('t') 't') | (&('b') 'b')))> */ + nil, + /* 29 basicUnescaped <- <((&(' ' | '!') [ -!]) | (&('#' | '$' | '%' | '&' | '\'' | '(' | ')' | '*' | '+' | ',' | '-' | '.' | '/' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | '[') [#-[]) | (&(']' | '^' | '_' | '`' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | '{' | '|' | '}' | '~' | '\u007f' | '\u0080' | '\u0081' | '\u0082' | '\u0083' | '\u0084' | '\u0085' | '\u0086' | '\u0087' | '\u0088' | '\u0089' | '\u008a' | '\u008b' | '\u008c' | '\u008d' | '\u008e' | '\u008f' | '\u0090' | '\u0091' | '\u0092' | '\u0093' | '\u0094' | '\u0095' | '\u0096' | '\u0097' | '\u0098' | '\u0099' | '\u009a' | '\u009b' | '\u009c' | '\u009d' | '\u009e' | '\u009f' | '\u00a0' | '¡' | '¢' | '£' | '¤' | '¥' | '¦' | '§' | '¨' | '©' | 'ª' | '«' | '¬' | '\u00ad' | '®' | '¯' | '°' | '±' | '²' | '³' | '´' | 'µ' | '¶' | '·' | '¸' | '¹' | 'º' | '»' | '¼' | '½' | '¾' | '¿' | 'À' | 'Á' | 'Â' | 'Ã' | 'Ä' | 'Å' | 'Æ' | 'Ç' | 'È' | 'É' | 'Ê' | 'Ë' | 'Ì' | 'Í' | 'Î' | 'Ï' | 'Ð' | 'Ñ' | 'Ò' | 'Ó' | 'Ô' | 'Õ' | 'Ö' | '×' | 'Ø' | 'Ù' | 'Ú' | 'Û' | 'Ü' | 'Ý' | 'Þ' | 'ß' | 'à' | 'á' | 'â' | 'ã' | 'ä' | 'å' | 'æ' | 'ç' | 'è' | 'é' | 'ê' | 'ë' | 'ì' | 'í' | 'î' | 'ï' | 'ð' | 'ñ' | 'ò' | 'ó' | 'ô' | 'õ' | 'ö' | '÷' | 'ø' | 'ù' | 'ú' | 'û' | 'ü' | 'ý' | 'þ' | 'ÿ') []-\U0010ffff]))> */ + nil, + /* 30 escape <- <'\\'> */ + func() bool { + position261, tokenIndex261 := position, tokenIndex + { + position262 := position + if buffer[position] != rune('\\') { + goto l261 + } + position++ + add(ruleescape, position262) + } + return true + l261: + position, tokenIndex = position261, tokenIndex261 + return false + }, + /* 31 mlBasicString <- <('"' '"' '"' mlBasicBody ('"' '"' '"') Action19)> */ + nil, + /* 32 mlBasicBody <- <((<(basicChar / newline)> Action20) / (escape newline wsnl))*> */ + nil, + /* 33 literalString <- <('\'' '\'' Action21)> */ + nil, + /* 34 literalChar <- <((&('\t') '\t') | (&(' ' | '!' | '"' | '#' | '$' | '%' | '&') [ -&]) | (&('(' | ')' | '*' | '+' | ',' | '-' | '.' | '/' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | '[' | '\\' | ']' | '^' | '_' | '`' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | '{' | '|' | '}' | '~' | '\u007f' | '\u0080' | '\u0081' | '\u0082' | '\u0083' | '\u0084' | '\u0085' | '\u0086' | '\u0087' | '\u0088' | '\u0089' | '\u008a' | '\u008b' | '\u008c' | '\u008d' | '\u008e' | '\u008f' | '\u0090' | '\u0091' | '\u0092' | '\u0093' | '\u0094' | '\u0095' | '\u0096' | '\u0097' | '\u0098' | '\u0099' | '\u009a' | '\u009b' | '\u009c' | '\u009d' | '\u009e' | '\u009f' | '\u00a0' | '¡' | '¢' | '£' | '¤' | '¥' | '¦' | '§' | '¨' | '©' | 'ª' | '«' | '¬' | '\u00ad' | '®' | '¯' | '°' | '±' | '²' | '³' | '´' | 'µ' | '¶' | '·' | '¸' | '¹' | 'º' | '»' | '¼' | '½' | '¾' | '¿' | 'À' | 'Á' | 'Â' | 'Ã' | 'Ä' | 'Å' | 'Æ' | 'Ç' | 'È' | 'É' | 'Ê' | 'Ë' | 'Ì' | 'Í' | 'Î' | 'Ï' | 'Ð' | 'Ñ' | 'Ò' | 'Ó' | 'Ô' | 'Õ' | 'Ö' | '×' | 'Ø' | 'Ù' | 'Ú' | 'Û' | 'Ü' | 'Ý' | 'Þ' | 'ß' | 'à' | 'á' | 'â' | 'ã' | 'ä' | 'å' | 'æ' | 'ç' | 'è' | 'é' | 'ê' | 'ë' | 'ì' | 'í' | 'î' | 'ï' | 'ð' | 'ñ' | 'ò' | 'ó' | 'ô' | 'õ' | 'ö' | '÷' | 'ø' | 'ù' | 'ú' | 'û' | 'ü' | 'ý' | 'þ' | 'ÿ') [(-\U0010ffff]))> */ + nil, + /* 35 mlLiteralString <- <('\'' '\'' '\'' ('\'' '\'' '\'') Action22)> */ + nil, + /* 36 mlLiteralBody <- <(!('\'' '\'' '\'') (mlLiteralChar / newline))*> */ + nil, + /* 37 mlLiteralChar <- <('\t' / [ -\U0010ffff])> */ + nil, + /* 38 hexdigit <- <((&('a' | 'b' | 'c' | 'd' | 'e' | 'f') [a-f]) | (&('A' | 'B' | 'C' | 'D' | 'E' | 'F') [A-F]) | (&('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') [0-9]))> */ + func() bool { + position270, tokenIndex270 := position, tokenIndex + { + position271 := position + { + switch buffer[position] { + case 'a', 'b', 'c', 'd', 'e', 'f': + if c := buffer[position]; c < rune('a') || c > rune('f') { + goto l270 + } + position++ + break + case 'A', 'B', 'C', 'D', 'E', 'F': + if c := buffer[position]; c < rune('A') || c > rune('F') { + goto l270 + } + position++ + break + default: + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l270 + } + position++ + break + } + } + + add(rulehexdigit, position271) + } + return true + l270: + position, tokenIndex = position270, tokenIndex270 + return false + }, + /* 39 hexQuad <- <(hexdigit hexdigit hexdigit hexdigit)> */ + func() bool { + position273, tokenIndex273 := position, tokenIndex + { + position274 := position + if !_rules[rulehexdigit]() { + goto l273 + } + if !_rules[rulehexdigit]() { + goto l273 + } + if !_rules[rulehexdigit]() { + goto l273 + } + if !_rules[rulehexdigit]() { + goto l273 + } + add(rulehexQuad, position274) + } + return true + l273: + position, tokenIndex = position273, tokenIndex273 + return false + }, + /* 40 boolean <- <(('t' 'r' 'u' 'e') / ('f' 'a' 'l' 's' 'e'))> */ + nil, + /* 41 dateFullYear <- */ + nil, + /* 42 dateMonth <- */ + nil, + /* 43 dateMDay <- */ + nil, + /* 44 timeHour <- */ + func() bool { + position279, tokenIndex279 := position, tokenIndex + { + position280 := position + if !_rules[ruledigitDual]() { + goto l279 + } + add(ruletimeHour, position280) + } + return true + l279: + position, tokenIndex = position279, tokenIndex279 + return false + }, + /* 45 timeMinute <- */ + func() bool { + position281, tokenIndex281 := position, tokenIndex + { + position282 := position + if !_rules[ruledigitDual]() { + goto l281 + } + add(ruletimeMinute, position282) + } + return true + l281: + position, tokenIndex = position281, tokenIndex281 + return false + }, + /* 46 timeSecond <- */ + nil, + /* 47 timeSecfrac <- <('.' digit+)> */ + nil, + /* 48 timeNumoffset <- <(('-' / '+') timeHour ':' timeMinute)> */ + nil, + /* 49 timeOffset <- <('Z' / timeNumoffset)> */ + nil, + /* 50 partialTime <- <(timeHour ':' timeMinute ':' timeSecond timeSecfrac?)> */ + func() bool { + position287, tokenIndex287 := position, tokenIndex + { + position288 := position + if !_rules[ruletimeHour]() { + goto l287 + } + if buffer[position] != rune(':') { + goto l287 + } + position++ + if !_rules[ruletimeMinute]() { + goto l287 + } + if buffer[position] != rune(':') { + goto l287 + } + position++ + { + position289 := position + if !_rules[ruledigitDual]() { + goto l287 + } + add(ruletimeSecond, position289) + } + { + position290, tokenIndex290 := position, tokenIndex + { + position292 := position + if buffer[position] != rune('.') { + goto l290 + } + position++ + if !_rules[ruledigit]() { + goto l290 + } + l293: + { + position294, tokenIndex294 := position, tokenIndex + if !_rules[ruledigit]() { + goto l294 + } + goto l293 + l294: + position, tokenIndex = position294, tokenIndex294 + } + add(ruletimeSecfrac, position292) + } + goto l291 + l290: + position, tokenIndex = position290, tokenIndex290 + } + l291: + add(rulepartialTime, position288) + } + return true + l287: + position, tokenIndex = position287, tokenIndex287 + return false + }, + /* 51 fullDate <- <(dateFullYear '-' dateMonth '-' dateMDay)> */ + nil, + /* 52 fullTime <- <(partialTime timeOffset)> */ + nil, + /* 53 datetime <- <((fullDate ('T' fullTime)?) / partialTime)> */ + nil, + /* 54 digit <- <[0-9]> */ + func() bool { + position298, tokenIndex298 := position, tokenIndex + { + position299 := position + if c := buffer[position]; c < rune('0') || c > rune('9') { + goto l298 + } + position++ + add(ruledigit, position299) + } + return true + l298: + position, tokenIndex = position298, tokenIndex298 + return false + }, + /* 55 digitDual <- <(digit digit)> */ + func() bool { + position300, tokenIndex300 := position, tokenIndex + { + position301 := position + if !_rules[ruledigit]() { + goto l300 + } + if !_rules[ruledigit]() { + goto l300 + } + add(ruledigitDual, position301) + } + return true + l300: + position, tokenIndex = position300, tokenIndex300 + return false + }, + /* 56 digitQuad <- <(digitDual digitDual)> */ + nil, + /* 57 array <- <('[' Action23 wsnl arrayValues? wsnl ']')> */ + nil, + /* 58 arrayValues <- <(val Action24 (wsnl comment? wsnl arraySep wsnl comment? wsnl val Action25)* wsnl arraySep? wsnl comment?)> */ + nil, + /* 59 arraySep <- <','> */ + func() bool { + position305, tokenIndex305 := position, tokenIndex + { + position306 := position + if buffer[position] != rune(',') { + goto l305 + } + position++ + add(rulearraySep, position306) + } + return true + l305: + position, tokenIndex = position305, tokenIndex305 + return false + }, + /* 61 Action0 <- <{ _ = buffer }> */ + nil, + nil, + /* 63 Action1 <- <{ p.SetTableString(begin, end) }> */ + nil, + /* 64 Action2 <- <{ p.AddLineCount(end - begin) }> */ + nil, + /* 65 Action3 <- <{ p.AddLineCount(end - begin) }> */ + nil, + /* 66 Action4 <- <{ p.AddKeyValue() }> */ + nil, + /* 67 Action5 <- <{ p.SetKey(p.buffer, begin, end) }> */ + nil, + /* 68 Action6 <- <{ p.SetKey(p.buffer, begin, end) }> */ + nil, + /* 69 Action7 <- <{ p.SetTime(begin, end) }> */ + nil, + /* 70 Action8 <- <{ p.SetFloat64(begin, end) }> */ + nil, + /* 71 Action9 <- <{ p.SetInt64(begin, end) }> */ + nil, + /* 72 Action10 <- <{ p.SetString(begin, end) }> */ + nil, + /* 73 Action11 <- <{ p.SetBool(begin, end) }> */ + nil, + /* 74 Action12 <- <{ p.SetArray(begin, end) }> */ + nil, + /* 75 Action13 <- <{ p.SetTable(p.buffer, begin, end) }> */ + nil, + /* 76 Action14 <- <{ p.SetArrayTable(p.buffer, begin, end) }> */ + nil, + /* 77 Action15 <- <{ p.StartInlineTable() }> */ + nil, + /* 78 Action16 <- <{ p.EndInlineTable() }> */ + nil, + /* 79 Action17 <- <{ p.AddTableKey() }> */ + nil, + /* 80 Action18 <- <{ p.SetBasicString(p.buffer, begin, end) }> */ + nil, + /* 81 Action19 <- <{ p.SetMultilineString() }> */ + nil, + /* 82 Action20 <- <{ p.AddMultilineBasicBody(p.buffer, begin, end) }> */ + nil, + /* 83 Action21 <- <{ p.SetLiteralString(p.buffer, begin, end) }> */ + nil, + /* 84 Action22 <- <{ p.SetMultilineLiteralString(p.buffer, begin, end) }> */ + nil, + /* 85 Action23 <- <{ p.StartArray() }> */ + nil, + /* 86 Action24 <- <{ p.AddArrayVal() }> */ + nil, + /* 87 Action25 <- <{ p.AddArrayVal() }> */ + nil, + } + p.rules = _rules +} diff --git a/vendor/github.com/naoina/toml/util.go b/vendor/github.com/naoina/toml/util.go new file mode 100644 index 00000000..f882f4e5 --- /dev/null +++ b/vendor/github.com/naoina/toml/util.go @@ -0,0 +1,65 @@ +package toml + +import ( + "fmt" + "reflect" + "strings" +) + +const fieldTagName = "toml" + +// fieldCache maps normalized field names to their position in a struct. +type fieldCache struct { + named map[string]fieldInfo // fields with an explicit name in tag + auto map[string]fieldInfo // fields with auto-assigned normalized names +} + +type fieldInfo struct { + index []int + name string + ignored bool +} + +func makeFieldCache(cfg *Config, rt reflect.Type) fieldCache { + named, auto := make(map[string]fieldInfo), make(map[string]fieldInfo) + for i := 0; i < rt.NumField(); i++ { + ft := rt.Field(i) + // skip unexported fields + if ft.PkgPath != "" && !ft.Anonymous { + continue + } + col, _ := extractTag(ft.Tag.Get(fieldTagName)) + info := fieldInfo{index: ft.Index, name: ft.Name, ignored: col == "-"} + if col == "" || col == "-" { + auto[cfg.NormFieldName(rt, ft.Name)] = info + } else { + named[col] = info + } + } + return fieldCache{named, auto} +} + +func (fc fieldCache) findField(cfg *Config, rv reflect.Value, name string) (reflect.Value, string, error) { + info, found := fc.named[name] + if !found { + info, found = fc.auto[cfg.NormFieldName(rv.Type(), name)] + } + if !found { + if cfg.MissingField == nil { + return reflect.Value{}, "", fmt.Errorf("field corresponding to `%s' is not defined in %v", name, rv.Type()) + } else { + return reflect.Value{}, "", cfg.MissingField(rv.Type(), name) + } + } else if info.ignored { + return reflect.Value{}, "", fmt.Errorf("field corresponding to `%s' in %v cannot be set through TOML", name, rv.Type()) + } + return rv.FieldByIndex(info.index), info.name, nil +} + +func extractTag(tag string) (col, rest string) { + tags := strings.SplitN(tag, ",", 2) + if len(tags) == 2 { + return strings.TrimSpace(tags[0]), strings.TrimSpace(tags[1]) + } + return strings.TrimSpace(tags[0]), "" +} diff --git a/vendor/github.com/rcrowley/go-metrics/LICENSE b/vendor/github.com/rcrowley/go-metrics/LICENSE new file mode 100644 index 00000000..363fa9ee --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/LICENSE @@ -0,0 +1,29 @@ +Copyright 2012 Richard Crowley. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +THIS SOFTWARE IS PROVIDED BY RICHARD CROWLEY ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL RICHARD CROWLEY OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of Richard Crowley. diff --git a/vendor/github.com/rcrowley/go-metrics/README.md b/vendor/github.com/rcrowley/go-metrics/README.md new file mode 100644 index 00000000..2d1a6dcf --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/README.md @@ -0,0 +1,153 @@ +go-metrics +========== + +![travis build status](https://travis-ci.org/rcrowley/go-metrics.svg?branch=master) + +Go port of Coda Hale's Metrics library: . + +Documentation: . + +Usage +----- + +Create and update metrics: + +```go +c := metrics.NewCounter() +metrics.Register("foo", c) +c.Inc(47) + +g := metrics.NewGauge() +metrics.Register("bar", g) +g.Update(47) + +r := NewRegistry() +g := metrics.NewRegisteredFunctionalGauge("cache-evictions", r, func() int64 { return cache.getEvictionsCount() }) + +s := metrics.NewExpDecaySample(1028, 0.015) // or metrics.NewUniformSample(1028) +h := metrics.NewHistogram(s) +metrics.Register("baz", h) +h.Update(47) + +m := metrics.NewMeter() +metrics.Register("quux", m) +m.Mark(47) + +t := metrics.NewTimer() +metrics.Register("bang", t) +t.Time(func() {}) +t.Update(47) +``` + +Register() is not threadsafe. For threadsafe metric registration use +GetOrRegister: + +``` +t := metrics.GetOrRegisterTimer("account.create.latency", nil) +t.Time(func() {}) +t.Update(47) +``` + +Periodically log every metric in human-readable form to standard error: + +```go +go metrics.Log(metrics.DefaultRegistry, 5 * time.Second, log.New(os.Stderr, "metrics: ", log.Lmicroseconds)) +``` + +Periodically log every metric in slightly-more-parseable form to syslog: + +```go +w, _ := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics") +go metrics.Syslog(metrics.DefaultRegistry, 60e9, w) +``` + +Periodically emit every metric to Graphite using the [Graphite client](https://github.com/cyberdelia/go-metrics-graphite): + +```go + +import "github.com/cyberdelia/go-metrics-graphite" + +addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003") +go graphite.Graphite(metrics.DefaultRegistry, 10e9, "metrics", addr) +``` + +Periodically emit every metric into InfluxDB: + +**NOTE:** this has been pulled out of the library due to constant fluctuations +in the InfluxDB API. In fact, all client libraries are on their way out. see +issues [#121](https://github.com/rcrowley/go-metrics/issues/121) and +[#124](https://github.com/rcrowley/go-metrics/issues/124) for progress and details. + +```go +import "github.com/vrischmann/go-metrics-influxdb" + +go influxdb.Influxdb(metrics.DefaultRegistry, 10e9, &influxdb.Config{ + Host: "127.0.0.1:8086", + Database: "metrics", + Username: "test", + Password: "test", +}) +``` + +Periodically upload every metric to Librato using the [Librato client](https://github.com/mihasya/go-metrics-librato): + +**Note**: the client included with this repository under the `librato` package +has been deprecated and moved to the repository linked above. + +```go +import "github.com/mihasya/go-metrics-librato" + +go librato.Librato(metrics.DefaultRegistry, + 10e9, // interval + "example@example.com", // account owner email address + "token", // Librato API token + "hostname", // source + []float64{0.95}, // percentiles to send + time.Millisecond, // time unit +) +``` + +Periodically emit every metric to StatHat: + +```go +import "github.com/rcrowley/go-metrics/stathat" + +go stathat.Stathat(metrics.DefaultRegistry, 10e9, "example@example.com") +``` + +Maintain all metrics along with expvars at `/debug/metrics`: + +This uses the same mechanism as [the official expvar](http://golang.org/pkg/expvar/) +but exposed under `/debug/metrics`, which shows a json representation of all your usual expvars +as well as all your go-metrics. + + +```go +import "github.com/rcrowley/go-metrics/exp" + +exp.Exp(metrics.DefaultRegistry) +``` + +Installation +------------ + +```sh +go get github.com/rcrowley/go-metrics +``` + +StatHat support additionally requires their Go client: + +```sh +go get github.com/stathat/go +``` + +Publishing Metrics +------------------ + +Clients are available for the following destinations: + +* Librato - [https://github.com/mihasya/go-metrics-librato](https://github.com/mihasya/go-metrics-librato) +* Graphite - [https://github.com/cyberdelia/go-metrics-graphite](https://github.com/cyberdelia/go-metrics-graphite) +* InfluxDB - [https://github.com/vrischmann/go-metrics-influxdb](https://github.com/vrischmann/go-metrics-influxdb) +* Ganglia - [https://github.com/appscode/metlia](https://github.com/appscode/metlia) +* Prometheus - [https://github.com/deathowl/go-metrics-prometheus](https://github.com/deathowl/go-metrics-prometheus) diff --git a/vendor/github.com/rcrowley/go-metrics/counter.go b/vendor/github.com/rcrowley/go-metrics/counter.go new file mode 100644 index 00000000..bb7b039c --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/counter.go @@ -0,0 +1,112 @@ +package metrics + +import "sync/atomic" + +// Counters hold an int64 value that can be incremented and decremented. +type Counter interface { + Clear() + Count() int64 + Dec(int64) + Inc(int64) + Snapshot() Counter +} + +// GetOrRegisterCounter returns an existing Counter or constructs and registers +// a new StandardCounter. +func GetOrRegisterCounter(name string, r Registry) Counter { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewCounter).(Counter) +} + +// NewCounter constructs a new StandardCounter. +func NewCounter() Counter { + if UseNilMetrics { + return NilCounter{} + } + return &StandardCounter{0} +} + +// NewRegisteredCounter constructs and registers a new StandardCounter. +func NewRegisteredCounter(name string, r Registry) Counter { + c := NewCounter() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// CounterSnapshot is a read-only copy of another Counter. +type CounterSnapshot int64 + +// Clear panics. +func (CounterSnapshot) Clear() { + panic("Clear called on a CounterSnapshot") +} + +// Count returns the count at the time the snapshot was taken. +func (c CounterSnapshot) Count() int64 { return int64(c) } + +// Dec panics. +func (CounterSnapshot) Dec(int64) { + panic("Dec called on a CounterSnapshot") +} + +// Inc panics. +func (CounterSnapshot) Inc(int64) { + panic("Inc called on a CounterSnapshot") +} + +// Snapshot returns the snapshot. +func (c CounterSnapshot) Snapshot() Counter { return c } + +// NilCounter is a no-op Counter. +type NilCounter struct{} + +// Clear is a no-op. +func (NilCounter) Clear() {} + +// Count is a no-op. +func (NilCounter) Count() int64 { return 0 } + +// Dec is a no-op. +func (NilCounter) Dec(i int64) {} + +// Inc is a no-op. +func (NilCounter) Inc(i int64) {} + +// Snapshot is a no-op. +func (NilCounter) Snapshot() Counter { return NilCounter{} } + +// StandardCounter is the standard implementation of a Counter and uses the +// sync/atomic package to manage a single int64 value. +type StandardCounter struct { + count int64 +} + +// Clear sets the counter to zero. +func (c *StandardCounter) Clear() { + atomic.StoreInt64(&c.count, 0) +} + +// Count returns the current count. +func (c *StandardCounter) Count() int64 { + return atomic.LoadInt64(&c.count) +} + +// Dec decrements the counter by the given amount. +func (c *StandardCounter) Dec(i int64) { + atomic.AddInt64(&c.count, -i) +} + +// Inc increments the counter by the given amount. +func (c *StandardCounter) Inc(i int64) { + atomic.AddInt64(&c.count, i) +} + +// Snapshot returns a read-only copy of the counter. +func (c *StandardCounter) Snapshot() Counter { + return CounterSnapshot(c.Count()) +} diff --git a/vendor/github.com/rcrowley/go-metrics/debug.go b/vendor/github.com/rcrowley/go-metrics/debug.go new file mode 100644 index 00000000..043ccefa --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/debug.go @@ -0,0 +1,76 @@ +package metrics + +import ( + "runtime/debug" + "time" +) + +var ( + debugMetrics struct { + GCStats struct { + LastGC Gauge + NumGC Gauge + Pause Histogram + //PauseQuantiles Histogram + PauseTotal Gauge + } + ReadGCStats Timer + } + gcStats debug.GCStats +) + +// Capture new values for the Go garbage collector statistics exported in +// debug.GCStats. This is designed to be called as a goroutine. +func CaptureDebugGCStats(r Registry, d time.Duration) { + for _ = range time.Tick(d) { + CaptureDebugGCStatsOnce(r) + } +} + +// Capture new values for the Go garbage collector statistics exported in +// debug.GCStats. This is designed to be called in a background goroutine. +// Giving a registry which has not been given to RegisterDebugGCStats will +// panic. +// +// Be careful (but much less so) with this because debug.ReadGCStats calls +// the C function runtime·lock(runtime·mheap) which, while not a stop-the-world +// operation, isn't something you want to be doing all the time. +func CaptureDebugGCStatsOnce(r Registry) { + lastGC := gcStats.LastGC + t := time.Now() + debug.ReadGCStats(&gcStats) + debugMetrics.ReadGCStats.UpdateSince(t) + + debugMetrics.GCStats.LastGC.Update(int64(gcStats.LastGC.UnixNano())) + debugMetrics.GCStats.NumGC.Update(int64(gcStats.NumGC)) + if lastGC != gcStats.LastGC && 0 < len(gcStats.Pause) { + debugMetrics.GCStats.Pause.Update(int64(gcStats.Pause[0])) + } + //debugMetrics.GCStats.PauseQuantiles.Update(gcStats.PauseQuantiles) + debugMetrics.GCStats.PauseTotal.Update(int64(gcStats.PauseTotal)) +} + +// Register metrics for the Go garbage collector statistics exported in +// debug.GCStats. The metrics are named by their fully-qualified Go symbols, +// i.e. debug.GCStats.PauseTotal. +func RegisterDebugGCStats(r Registry) { + debugMetrics.GCStats.LastGC = NewGauge() + debugMetrics.GCStats.NumGC = NewGauge() + debugMetrics.GCStats.Pause = NewHistogram(NewExpDecaySample(1028, 0.015)) + //debugMetrics.GCStats.PauseQuantiles = NewHistogram(NewExpDecaySample(1028, 0.015)) + debugMetrics.GCStats.PauseTotal = NewGauge() + debugMetrics.ReadGCStats = NewTimer() + + r.Register("debug.GCStats.LastGC", debugMetrics.GCStats.LastGC) + r.Register("debug.GCStats.NumGC", debugMetrics.GCStats.NumGC) + r.Register("debug.GCStats.Pause", debugMetrics.GCStats.Pause) + //r.Register("debug.GCStats.PauseQuantiles", debugMetrics.GCStats.PauseQuantiles) + r.Register("debug.GCStats.PauseTotal", debugMetrics.GCStats.PauseTotal) + r.Register("debug.ReadGCStats", debugMetrics.ReadGCStats) +} + +// Allocate an initial slice for gcStats.Pause to avoid allocations during +// normal operation. +func init() { + gcStats.Pause = make([]time.Duration, 11) +} diff --git a/vendor/github.com/rcrowley/go-metrics/ewma.go b/vendor/github.com/rcrowley/go-metrics/ewma.go new file mode 100644 index 00000000..694a1d03 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/ewma.go @@ -0,0 +1,118 @@ +package metrics + +import ( + "math" + "sync" + "sync/atomic" +) + +// EWMAs continuously calculate an exponentially-weighted moving average +// based on an outside source of clock ticks. +type EWMA interface { + Rate() float64 + Snapshot() EWMA + Tick() + Update(int64) +} + +// NewEWMA constructs a new EWMA with the given alpha. +func NewEWMA(alpha float64) EWMA { + if UseNilMetrics { + return NilEWMA{} + } + return &StandardEWMA{alpha: alpha} +} + +// NewEWMA1 constructs a new EWMA for a one-minute moving average. +func NewEWMA1() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/1)) +} + +// NewEWMA5 constructs a new EWMA for a five-minute moving average. +func NewEWMA5() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/5)) +} + +// NewEWMA15 constructs a new EWMA for a fifteen-minute moving average. +func NewEWMA15() EWMA { + return NewEWMA(1 - math.Exp(-5.0/60.0/15)) +} + +// EWMASnapshot is a read-only copy of another EWMA. +type EWMASnapshot float64 + +// Rate returns the rate of events per second at the time the snapshot was +// taken. +func (a EWMASnapshot) Rate() float64 { return float64(a) } + +// Snapshot returns the snapshot. +func (a EWMASnapshot) Snapshot() EWMA { return a } + +// Tick panics. +func (EWMASnapshot) Tick() { + panic("Tick called on an EWMASnapshot") +} + +// Update panics. +func (EWMASnapshot) Update(int64) { + panic("Update called on an EWMASnapshot") +} + +// NilEWMA is a no-op EWMA. +type NilEWMA struct{} + +// Rate is a no-op. +func (NilEWMA) Rate() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilEWMA) Snapshot() EWMA { return NilEWMA{} } + +// Tick is a no-op. +func (NilEWMA) Tick() {} + +// Update is a no-op. +func (NilEWMA) Update(n int64) {} + +// StandardEWMA is the standard implementation of an EWMA and tracks the number +// of uncounted events and processes them on each tick. It uses the +// sync/atomic package to manage uncounted events. +type StandardEWMA struct { + uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment + alpha float64 + rate float64 + init bool + mutex sync.Mutex +} + +// Rate returns the moving average rate of events per second. +func (a *StandardEWMA) Rate() float64 { + a.mutex.Lock() + defer a.mutex.Unlock() + return a.rate * float64(1e9) +} + +// Snapshot returns a read-only copy of the EWMA. +func (a *StandardEWMA) Snapshot() EWMA { + return EWMASnapshot(a.Rate()) +} + +// Tick ticks the clock to update the moving average. It assumes it is called +// every five seconds. +func (a *StandardEWMA) Tick() { + count := atomic.LoadInt64(&a.uncounted) + atomic.AddInt64(&a.uncounted, -count) + instantRate := float64(count) / float64(5e9) + a.mutex.Lock() + defer a.mutex.Unlock() + if a.init { + a.rate += a.alpha * (instantRate - a.rate) + } else { + a.init = true + a.rate = instantRate + } +} + +// Update adds n uncounted events. +func (a *StandardEWMA) Update(n int64) { + atomic.AddInt64(&a.uncounted, n) +} diff --git a/vendor/github.com/rcrowley/go-metrics/gauge.go b/vendor/github.com/rcrowley/go-metrics/gauge.go new file mode 100644 index 00000000..cb57a938 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/gauge.go @@ -0,0 +1,120 @@ +package metrics + +import "sync/atomic" + +// Gauges hold an int64 value that can be set arbitrarily. +type Gauge interface { + Snapshot() Gauge + Update(int64) + Value() int64 +} + +// GetOrRegisterGauge returns an existing Gauge or constructs and registers a +// new StandardGauge. +func GetOrRegisterGauge(name string, r Registry) Gauge { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGauge).(Gauge) +} + +// NewGauge constructs a new StandardGauge. +func NewGauge() Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &StandardGauge{0} +} + +// NewRegisteredGauge constructs and registers a new StandardGauge. +func NewRegisteredGauge(name string, r Registry) Gauge { + c := NewGauge() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGauge(f func() int64) Gauge { + if UseNilMetrics { + return NilGauge{} + } + return &FunctionalGauge{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge { + c := NewFunctionalGauge(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// GaugeSnapshot is a read-only copy of another Gauge. +type GaugeSnapshot int64 + +// Snapshot returns the snapshot. +func (g GaugeSnapshot) Snapshot() Gauge { return g } + +// Update panics. +func (GaugeSnapshot) Update(int64) { + panic("Update called on a GaugeSnapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeSnapshot) Value() int64 { return int64(g) } + +// NilGauge is a no-op Gauge. +type NilGauge struct{} + +// Snapshot is a no-op. +func (NilGauge) Snapshot() Gauge { return NilGauge{} } + +// Update is a no-op. +func (NilGauge) Update(v int64) {} + +// Value is a no-op. +func (NilGauge) Value() int64 { return 0 } + +// StandardGauge is the standard implementation of a Gauge and uses the +// sync/atomic package to manage a single int64 value. +type StandardGauge struct { + value int64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGauge) Snapshot() Gauge { + return GaugeSnapshot(g.Value()) +} + +// Update updates the gauge's value. +func (g *StandardGauge) Update(v int64) { + atomic.StoreInt64(&g.value, v) +} + +// Value returns the gauge's current value. +func (g *StandardGauge) Value() int64 { + return atomic.LoadInt64(&g.value) +} + +// FunctionalGauge returns value from given function +type FunctionalGauge struct { + value func() int64 +} + +// Value returns the gauge's current value. +func (g FunctionalGauge) Value() int64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) } + +// Update panics. +func (FunctionalGauge) Update(int64) { + panic("Update called on a FunctionalGauge") +} diff --git a/vendor/github.com/rcrowley/go-metrics/gauge_float64.go b/vendor/github.com/rcrowley/go-metrics/gauge_float64.go new file mode 100644 index 00000000..6f93920b --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/gauge_float64.go @@ -0,0 +1,127 @@ +package metrics + +import "sync" + +// GaugeFloat64s hold a float64 value that can be set arbitrarily. +type GaugeFloat64 interface { + Snapshot() GaugeFloat64 + Update(float64) + Value() float64 +} + +// GetOrRegisterGaugeFloat64 returns an existing GaugeFloat64 or constructs and registers a +// new StandardGaugeFloat64. +func GetOrRegisterGaugeFloat64(name string, r Registry) GaugeFloat64 { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewGaugeFloat64()).(GaugeFloat64) +} + +// NewGaugeFloat64 constructs a new StandardGaugeFloat64. +func NewGaugeFloat64() GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &StandardGaugeFloat64{ + value: 0.0, + } +} + +// NewRegisteredGaugeFloat64 constructs and registers a new StandardGaugeFloat64. +func NewRegisteredGaugeFloat64(name string, r Registry) GaugeFloat64 { + c := NewGaugeFloat64() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewFunctionalGauge constructs a new FunctionalGauge. +func NewFunctionalGaugeFloat64(f func() float64) GaugeFloat64 { + if UseNilMetrics { + return NilGaugeFloat64{} + } + return &FunctionalGaugeFloat64{value: f} +} + +// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge. +func NewRegisteredFunctionalGaugeFloat64(name string, r Registry, f func() float64) GaugeFloat64 { + c := NewFunctionalGaugeFloat64(f) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// GaugeFloat64Snapshot is a read-only copy of another GaugeFloat64. +type GaugeFloat64Snapshot float64 + +// Snapshot returns the snapshot. +func (g GaugeFloat64Snapshot) Snapshot() GaugeFloat64 { return g } + +// Update panics. +func (GaugeFloat64Snapshot) Update(float64) { + panic("Update called on a GaugeFloat64Snapshot") +} + +// Value returns the value at the time the snapshot was taken. +func (g GaugeFloat64Snapshot) Value() float64 { return float64(g) } + +// NilGauge is a no-op Gauge. +type NilGaugeFloat64 struct{} + +// Snapshot is a no-op. +func (NilGaugeFloat64) Snapshot() GaugeFloat64 { return NilGaugeFloat64{} } + +// Update is a no-op. +func (NilGaugeFloat64) Update(v float64) {} + +// Value is a no-op. +func (NilGaugeFloat64) Value() float64 { return 0.0 } + +// StandardGaugeFloat64 is the standard implementation of a GaugeFloat64 and uses +// sync.Mutex to manage a single float64 value. +type StandardGaugeFloat64 struct { + mutex sync.Mutex + value float64 +} + +// Snapshot returns a read-only copy of the gauge. +func (g *StandardGaugeFloat64) Snapshot() GaugeFloat64 { + return GaugeFloat64Snapshot(g.Value()) +} + +// Update updates the gauge's value. +func (g *StandardGaugeFloat64) Update(v float64) { + g.mutex.Lock() + defer g.mutex.Unlock() + g.value = v +} + +// Value returns the gauge's current value. +func (g *StandardGaugeFloat64) Value() float64 { + g.mutex.Lock() + defer g.mutex.Unlock() + return g.value +} + +// FunctionalGaugeFloat64 returns value from given function +type FunctionalGaugeFloat64 struct { + value func() float64 +} + +// Value returns the gauge's current value. +func (g FunctionalGaugeFloat64) Value() float64 { + return g.value() +} + +// Snapshot returns the snapshot. +func (g FunctionalGaugeFloat64) Snapshot() GaugeFloat64 { return GaugeFloat64Snapshot(g.Value()) } + +// Update panics. +func (FunctionalGaugeFloat64) Update(float64) { + panic("Update called on a FunctionalGaugeFloat64") +} diff --git a/vendor/github.com/rcrowley/go-metrics/graphite.go b/vendor/github.com/rcrowley/go-metrics/graphite.go new file mode 100644 index 00000000..abd0a7d2 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/graphite.go @@ -0,0 +1,113 @@ +package metrics + +import ( + "bufio" + "fmt" + "log" + "net" + "strconv" + "strings" + "time" +) + +// GraphiteConfig provides a container with configuration parameters for +// the Graphite exporter +type GraphiteConfig struct { + Addr *net.TCPAddr // Network address to connect to + Registry Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names + Percentiles []float64 // Percentiles to export from timers and histograms +} + +// Graphite is a blocking exporter function which reports metrics in r +// to a graphite server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func Graphite(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + GraphiteWithConfig(GraphiteConfig{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + Percentiles: []float64{0.5, 0.75, 0.95, 0.99, 0.999}, + }) +} + +// GraphiteWithConfig is a blocking exporter function just like Graphite, +// but it takes a GraphiteConfig instead. +func GraphiteWithConfig(c GraphiteConfig) { + log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") + for _ = range time.Tick(c.FlushInterval) { + if err := graphite(&c); nil != err { + log.Println(err) + } + } +} + +// GraphiteOnce performs a single submission to Graphite, returning a +// non-nil error on failed connections. This can be used in a loop +// similar to GraphiteWithConfig for custom error handling. +func GraphiteOnce(c GraphiteConfig) error { + log.Printf("WARNING: This go-metrics client has been DEPRECATED! It has been moved to https://github.com/cyberdelia/go-metrics-graphite and will be removed from rcrowley/go-metrics on August 12th 2015") + return graphite(&c) +} + +func graphite(c *GraphiteConfig) error { + now := time.Now().Unix() + du := float64(c.DurationUnit) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, metric.Count(), now) + case Gauge: + fmt.Fprintf(w, "%s.%s.value %d %d\n", c.Prefix, name, metric.Value(), now) + case GaugeFloat64: + fmt.Fprintf(w, "%s.%s.value %f %d\n", c.Prefix, name, metric.Value(), now) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, h.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, h.Min(), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, h.Max(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, h.Mean(), now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, h.StdDev(), now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, m.Count(), now) + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, m.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, m.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, m.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, m.RateMean(), now) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles(c.Percentiles) + fmt.Fprintf(w, "%s.%s.count %d %d\n", c.Prefix, name, t.Count(), now) + fmt.Fprintf(w, "%s.%s.min %d %d\n", c.Prefix, name, t.Min()/int64(du), now) + fmt.Fprintf(w, "%s.%s.max %d %d\n", c.Prefix, name, t.Max()/int64(du), now) + fmt.Fprintf(w, "%s.%s.mean %.2f %d\n", c.Prefix, name, t.Mean()/du, now) + fmt.Fprintf(w, "%s.%s.std-dev %.2f %d\n", c.Prefix, name, t.StdDev()/du, now) + for psIdx, psKey := range c.Percentiles { + key := strings.Replace(strconv.FormatFloat(psKey*100.0, 'f', -1, 64), ".", "", 1) + fmt.Fprintf(w, "%s.%s.%s-percentile %.2f %d\n", c.Prefix, name, key, ps[psIdx], now) + } + fmt.Fprintf(w, "%s.%s.one-minute %.2f %d\n", c.Prefix, name, t.Rate1(), now) + fmt.Fprintf(w, "%s.%s.five-minute %.2f %d\n", c.Prefix, name, t.Rate5(), now) + fmt.Fprintf(w, "%s.%s.fifteen-minute %.2f %d\n", c.Prefix, name, t.Rate15(), now) + fmt.Fprintf(w, "%s.%s.mean-rate %.2f %d\n", c.Prefix, name, t.RateMean(), now) + } + w.Flush() + }) + return nil +} diff --git a/vendor/github.com/rcrowley/go-metrics/healthcheck.go b/vendor/github.com/rcrowley/go-metrics/healthcheck.go new file mode 100644 index 00000000..445131ca --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/healthcheck.go @@ -0,0 +1,61 @@ +package metrics + +// Healthchecks hold an error value describing an arbitrary up/down status. +type Healthcheck interface { + Check() + Error() error + Healthy() + Unhealthy(error) +} + +// NewHealthcheck constructs a new Healthcheck which will use the given +// function to update its status. +func NewHealthcheck(f func(Healthcheck)) Healthcheck { + if UseNilMetrics { + return NilHealthcheck{} + } + return &StandardHealthcheck{nil, f} +} + +// NilHealthcheck is a no-op. +type NilHealthcheck struct{} + +// Check is a no-op. +func (NilHealthcheck) Check() {} + +// Error is a no-op. +func (NilHealthcheck) Error() error { return nil } + +// Healthy is a no-op. +func (NilHealthcheck) Healthy() {} + +// Unhealthy is a no-op. +func (NilHealthcheck) Unhealthy(error) {} + +// StandardHealthcheck is the standard implementation of a Healthcheck and +// stores the status and a function to call to update the status. +type StandardHealthcheck struct { + err error + f func(Healthcheck) +} + +// Check runs the healthcheck function to update the healthcheck's status. +func (h *StandardHealthcheck) Check() { + h.f(h) +} + +// Error returns the healthcheck's status, which will be nil if it is healthy. +func (h *StandardHealthcheck) Error() error { + return h.err +} + +// Healthy marks the healthcheck as healthy. +func (h *StandardHealthcheck) Healthy() { + h.err = nil +} + +// Unhealthy marks the healthcheck as unhealthy. The error is stored and +// may be retrieved by the Error method. +func (h *StandardHealthcheck) Unhealthy(err error) { + h.err = err +} diff --git a/vendor/github.com/rcrowley/go-metrics/histogram.go b/vendor/github.com/rcrowley/go-metrics/histogram.go new file mode 100644 index 00000000..dbc837fe --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/histogram.go @@ -0,0 +1,202 @@ +package metrics + +// Histograms calculate distribution statistics from a series of int64 values. +type Histogram interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Sample() Sample + Snapshot() Histogram + StdDev() float64 + Sum() int64 + Update(int64) + Variance() float64 +} + +// GetOrRegisterHistogram returns an existing Histogram or constructs and +// registers a new StandardHistogram. +func GetOrRegisterHistogram(name string, r Registry, s Sample) Histogram { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, func() Histogram { return NewHistogram(s) }).(Histogram) +} + +// NewHistogram constructs a new StandardHistogram from a Sample. +func NewHistogram(s Sample) Histogram { + if UseNilMetrics { + return NilHistogram{} + } + return &StandardHistogram{sample: s} +} + +// NewRegisteredHistogram constructs and registers a new StandardHistogram from +// a Sample. +func NewRegisteredHistogram(name string, r Registry, s Sample) Histogram { + c := NewHistogram(s) + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// HistogramSnapshot is a read-only copy of another Histogram. +type HistogramSnapshot struct { + sample *SampleSnapshot +} + +// Clear panics. +func (*HistogramSnapshot) Clear() { + panic("Clear called on a HistogramSnapshot") +} + +// Count returns the number of samples recorded at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample at the time the snapshot +// was taken. +func (h *HistogramSnapshot) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample at the time the snapshot was +// taken. +func (h *HistogramSnapshot) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the sample +// at the time the snapshot was taken. +func (h *HistogramSnapshot) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *HistogramSnapshot) Sample() Sample { return h.sample } + +// Snapshot returns the snapshot. +func (h *HistogramSnapshot) Snapshot() Histogram { return h } + +// StdDev returns the standard deviation of the values in the sample at the +// time the snapshot was taken. +func (h *HistogramSnapshot) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample at the time the snapshot was taken. +func (h *HistogramSnapshot) Sum() int64 { return h.sample.Sum() } + +// Update panics. +func (*HistogramSnapshot) Update(int64) { + panic("Update called on a HistogramSnapshot") +} + +// Variance returns the variance of inputs at the time the snapshot was taken. +func (h *HistogramSnapshot) Variance() float64 { return h.sample.Variance() } + +// NilHistogram is a no-op Histogram. +type NilHistogram struct{} + +// Clear is a no-op. +func (NilHistogram) Clear() {} + +// Count is a no-op. +func (NilHistogram) Count() int64 { return 0 } + +// Max is a no-op. +func (NilHistogram) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilHistogram) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilHistogram) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilHistogram) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilHistogram) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Sample is a no-op. +func (NilHistogram) Sample() Sample { return NilSample{} } + +// Snapshot is a no-op. +func (NilHistogram) Snapshot() Histogram { return NilHistogram{} } + +// StdDev is a no-op. +func (NilHistogram) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilHistogram) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilHistogram) Update(v int64) {} + +// Variance is a no-op. +func (NilHistogram) Variance() float64 { return 0.0 } + +// StandardHistogram is the standard implementation of a Histogram and uses a +// Sample to bound its memory use. +type StandardHistogram struct { + sample Sample +} + +// Clear clears the histogram and its sample. +func (h *StandardHistogram) Clear() { h.sample.Clear() } + +// Count returns the number of samples recorded since the histogram was last +// cleared. +func (h *StandardHistogram) Count() int64 { return h.sample.Count() } + +// Max returns the maximum value in the sample. +func (h *StandardHistogram) Max() int64 { return h.sample.Max() } + +// Mean returns the mean of the values in the sample. +func (h *StandardHistogram) Mean() float64 { return h.sample.Mean() } + +// Min returns the minimum value in the sample. +func (h *StandardHistogram) Min() int64 { return h.sample.Min() } + +// Percentile returns an arbitrary percentile of the values in the sample. +func (h *StandardHistogram) Percentile(p float64) float64 { + return h.sample.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (h *StandardHistogram) Percentiles(ps []float64) []float64 { + return h.sample.Percentiles(ps) +} + +// Sample returns the Sample underlying the histogram. +func (h *StandardHistogram) Sample() Sample { return h.sample } + +// Snapshot returns a read-only copy of the histogram. +func (h *StandardHistogram) Snapshot() Histogram { + return &HistogramSnapshot{sample: h.sample.Snapshot().(*SampleSnapshot)} +} + +// StdDev returns the standard deviation of the values in the sample. +func (h *StandardHistogram) StdDev() float64 { return h.sample.StdDev() } + +// Sum returns the sum in the sample. +func (h *StandardHistogram) Sum() int64 { return h.sample.Sum() } + +// Update samples a new value. +func (h *StandardHistogram) Update(v int64) { h.sample.Update(v) } + +// Variance returns the variance of the values in the sample. +func (h *StandardHistogram) Variance() float64 { return h.sample.Variance() } diff --git a/vendor/github.com/rcrowley/go-metrics/json.go b/vendor/github.com/rcrowley/go-metrics/json.go new file mode 100644 index 00000000..2fdcbcfb --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/json.go @@ -0,0 +1,87 @@ +package metrics + +import ( + "encoding/json" + "io" + "time" +) + +// MarshalJSON returns a byte slice containing a JSON representation of all +// the metrics in the Registry. +func (r *StandardRegistry) MarshalJSON() ([]byte, error) { + data := make(map[string]map[string]interface{}) + r.Each(func(name string, i interface{}) { + values := make(map[string]interface{}) + switch metric := i.(type) { + case Counter: + values["count"] = metric.Count() + case Gauge: + values["value"] = metric.Value() + case GaugeFloat64: + values["value"] = metric.Value() + case Healthcheck: + values["error"] = nil + metric.Check() + if err := metric.Error(); nil != err { + values["error"] = metric.Error().Error() + } + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = h.Count() + values["min"] = h.Min() + values["max"] = h.Max() + values["mean"] = h.Mean() + values["stddev"] = h.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + case Meter: + m := metric.Snapshot() + values["count"] = m.Count() + values["1m.rate"] = m.Rate1() + values["5m.rate"] = m.Rate5() + values["15m.rate"] = m.Rate15() + values["mean.rate"] = m.RateMean() + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + values["count"] = t.Count() + values["min"] = t.Min() + values["max"] = t.Max() + values["mean"] = t.Mean() + values["stddev"] = t.StdDev() + values["median"] = ps[0] + values["75%"] = ps[1] + values["95%"] = ps[2] + values["99%"] = ps[3] + values["99.9%"] = ps[4] + values["1m.rate"] = t.Rate1() + values["5m.rate"] = t.Rate5() + values["15m.rate"] = t.Rate15() + values["mean.rate"] = t.RateMean() + } + data[name] = values + }) + return json.Marshal(data) +} + +// WriteJSON writes metrics from the given registry periodically to the +// specified io.Writer as JSON. +func WriteJSON(r Registry, d time.Duration, w io.Writer) { + for _ = range time.Tick(d) { + WriteJSONOnce(r, w) + } +} + +// WriteJSONOnce writes metrics from the given registry to the specified +// io.Writer as JSON. +func WriteJSONOnce(r Registry, w io.Writer) { + json.NewEncoder(w).Encode(r) +} + +func (p *PrefixedRegistry) MarshalJSON() ([]byte, error) { + return json.Marshal(p.underlying) +} diff --git a/vendor/github.com/rcrowley/go-metrics/log.go b/vendor/github.com/rcrowley/go-metrics/log.go new file mode 100644 index 00000000..f8074c04 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/log.go @@ -0,0 +1,80 @@ +package metrics + +import ( + "time" +) + +type Logger interface { + Printf(format string, v ...interface{}) +} + +func Log(r Registry, freq time.Duration, l Logger) { + LogScaled(r, freq, time.Nanosecond, l) +} + +// Output each metric in the given registry periodically using the given +// logger. Print timings in `scale` units (eg time.Millisecond) rather than nanos. +func LogScaled(r Registry, freq time.Duration, scale time.Duration, l Logger) { + du := float64(scale) + duSuffix := scale.String()[1:] + + for _ = range time.Tick(freq) { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + l.Printf("counter %s\n", name) + l.Printf(" count: %9d\n", metric.Count()) + case Gauge: + l.Printf("gauge %s\n", name) + l.Printf(" value: %9d\n", metric.Value()) + case GaugeFloat64: + l.Printf("gauge %s\n", name) + l.Printf(" value: %f\n", metric.Value()) + case Healthcheck: + metric.Check() + l.Printf("healthcheck %s\n", name) + l.Printf(" error: %v\n", metric.Error()) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + l.Printf("histogram %s\n", name) + l.Printf(" count: %9d\n", h.Count()) + l.Printf(" min: %9d\n", h.Min()) + l.Printf(" max: %9d\n", h.Max()) + l.Printf(" mean: %12.2f\n", h.Mean()) + l.Printf(" stddev: %12.2f\n", h.StdDev()) + l.Printf(" median: %12.2f\n", ps[0]) + l.Printf(" 75%%: %12.2f\n", ps[1]) + l.Printf(" 95%%: %12.2f\n", ps[2]) + l.Printf(" 99%%: %12.2f\n", ps[3]) + l.Printf(" 99.9%%: %12.2f\n", ps[4]) + case Meter: + m := metric.Snapshot() + l.Printf("meter %s\n", name) + l.Printf(" count: %9d\n", m.Count()) + l.Printf(" 1-min rate: %12.2f\n", m.Rate1()) + l.Printf(" 5-min rate: %12.2f\n", m.Rate5()) + l.Printf(" 15-min rate: %12.2f\n", m.Rate15()) + l.Printf(" mean rate: %12.2f\n", m.RateMean()) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + l.Printf("timer %s\n", name) + l.Printf(" count: %9d\n", t.Count()) + l.Printf(" min: %12.2f%s\n", float64(t.Min())/du, duSuffix) + l.Printf(" max: %12.2f%s\n", float64(t.Max())/du, duSuffix) + l.Printf(" mean: %12.2f%s\n", t.Mean()/du, duSuffix) + l.Printf(" stddev: %12.2f%s\n", t.StdDev()/du, duSuffix) + l.Printf(" median: %12.2f%s\n", ps[0]/du, duSuffix) + l.Printf(" 75%%: %12.2f%s\n", ps[1]/du, duSuffix) + l.Printf(" 95%%: %12.2f%s\n", ps[2]/du, duSuffix) + l.Printf(" 99%%: %12.2f%s\n", ps[3]/du, duSuffix) + l.Printf(" 99.9%%: %12.2f%s\n", ps[4]/du, duSuffix) + l.Printf(" 1-min rate: %12.2f\n", t.Rate1()) + l.Printf(" 5-min rate: %12.2f\n", t.Rate5()) + l.Printf(" 15-min rate: %12.2f\n", t.Rate15()) + l.Printf(" mean rate: %12.2f\n", t.RateMean()) + } + }) + } +} diff --git a/vendor/github.com/rcrowley/go-metrics/memory.md b/vendor/github.com/rcrowley/go-metrics/memory.md new file mode 100644 index 00000000..47454f54 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/memory.md @@ -0,0 +1,285 @@ +Memory usage +============ + +(Highly unscientific.) + +Command used to gather static memory usage: + +```sh +grep ^Vm "/proc/$(ps fax | grep [m]etrics-bench | awk '{print $1}')/status" +``` + +Program used to gather baseline memory usage: + +```go +package main + +import "time" + +func main() { + time.Sleep(600e9) +} +``` + +Baseline +-------- + +``` +VmPeak: 42604 kB +VmSize: 42604 kB +VmLck: 0 kB +VmHWM: 1120 kB +VmRSS: 1120 kB +VmData: 35460 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 36 kB +VmSwap: 0 kB +``` + +Program used to gather metric memory usage (with other metrics being similar): + +```go +package main + +import ( + "fmt" + "metrics" + "time" +) + +func main() { + fmt.Sprintf("foo") + metrics.NewRegistry() + time.Sleep(600e9) +} +``` + +1000 counters registered +------------------------ + +``` +VmPeak: 44016 kB +VmSize: 44016 kB +VmLck: 0 kB +VmHWM: 1928 kB +VmRSS: 1928 kB +VmData: 36868 kB +VmStk: 136 kB +VmExe: 1024 kB +VmLib: 1848 kB +VmPTE: 40 kB +VmSwap: 0 kB +``` + +**1.412 kB virtual, TODO 0.808 kB resident per counter.** + +100000 counters registered +-------------------------- + +``` +VmPeak: 55024 kB +VmSize: 55024 kB +VmLck: 0 kB +VmHWM: 12440 kB +VmRSS: 12440 kB +VmData: 47876 kB +VmStk: 136 kB +VmExe: 1024 kB +VmLib: 1848 kB +VmPTE: 64 kB +VmSwap: 0 kB +``` + +**0.1242 kB virtual, 0.1132 kB resident per counter.** + +1000 gauges registered +---------------------- + +``` +VmPeak: 44012 kB +VmSize: 44012 kB +VmLck: 0 kB +VmHWM: 1928 kB +VmRSS: 1928 kB +VmData: 36868 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 40 kB +VmSwap: 0 kB +``` + +**1.408 kB virtual, 0.808 kB resident per counter.** + +100000 gauges registered +------------------------ + +``` +VmPeak: 55020 kB +VmSize: 55020 kB +VmLck: 0 kB +VmHWM: 12432 kB +VmRSS: 12432 kB +VmData: 47876 kB +VmStk: 136 kB +VmExe: 1020 kB +VmLib: 1848 kB +VmPTE: 60 kB +VmSwap: 0 kB +``` + +**0.12416 kB virtual, 0.11312 resident per gauge.** + +1000 histograms with a uniform sample size of 1028 +-------------------------------------------------- + +``` +VmPeak: 72272 kB +VmSize: 72272 kB +VmLck: 0 kB +VmHWM: 16204 kB +VmRSS: 16204 kB +VmData: 65100 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 80 kB +VmSwap: 0 kB +``` + +**29.668 kB virtual, TODO 15.084 resident per histogram.** + +10000 histograms with a uniform sample size of 1028 +--------------------------------------------------- + +``` +VmPeak: 256912 kB +VmSize: 256912 kB +VmLck: 0 kB +VmHWM: 146204 kB +VmRSS: 146204 kB +VmData: 249740 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 448 kB +VmSwap: 0 kB +``` + +**21.4308 kB virtual, 14.5084 kB resident per histogram.** + +50000 histograms with a uniform sample size of 1028 +--------------------------------------------------- + +``` +VmPeak: 908112 kB +VmSize: 908112 kB +VmLck: 0 kB +VmHWM: 645832 kB +VmRSS: 645588 kB +VmData: 900940 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 1716 kB +VmSwap: 1544 kB +``` + +**17.31016 kB virtual, 12.88936 kB resident per histogram.** + +1000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +------------------------------------------------------------------------------------- + +``` +VmPeak: 62480 kB +VmSize: 62480 kB +VmLck: 0 kB +VmHWM: 11572 kB +VmRSS: 11572 kB +VmData: 55308 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 64 kB +VmSwap: 0 kB +``` + +**19.876 kB virtual, 10.452 kB resident per histogram.** + +10000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +-------------------------------------------------------------------------------------- + +``` +VmPeak: 153296 kB +VmSize: 153296 kB +VmLck: 0 kB +VmHWM: 101176 kB +VmRSS: 101176 kB +VmData: 146124 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 240 kB +VmSwap: 0 kB +``` + +**11.0692 kB virtual, 10.0056 kB resident per histogram.** + +50000 histograms with an exponentially-decaying sample size of 1028 and alpha of 0.015 +-------------------------------------------------------------------------------------- + +``` +VmPeak: 557264 kB +VmSize: 557264 kB +VmLck: 0 kB +VmHWM: 501056 kB +VmRSS: 501056 kB +VmData: 550092 kB +VmStk: 136 kB +VmExe: 1048 kB +VmLib: 1848 kB +VmPTE: 1032 kB +VmSwap: 0 kB +``` + +**10.2932 kB virtual, 9.99872 kB resident per histogram.** + +1000 meters +----------- + +``` +VmPeak: 74504 kB +VmSize: 74504 kB +VmLck: 0 kB +VmHWM: 24124 kB +VmRSS: 24124 kB +VmData: 67340 kB +VmStk: 136 kB +VmExe: 1040 kB +VmLib: 1848 kB +VmPTE: 92 kB +VmSwap: 0 kB +``` + +**31.9 kB virtual, 23.004 kB resident per meter.** + +10000 meters +------------ + +``` +VmPeak: 278920 kB +VmSize: 278920 kB +VmLck: 0 kB +VmHWM: 227300 kB +VmRSS: 227300 kB +VmData: 271756 kB +VmStk: 136 kB +VmExe: 1040 kB +VmLib: 1848 kB +VmPTE: 488 kB +VmSwap: 0 kB +``` + +**23.6316 kB virtual, 22.618 kB resident per meter.** diff --git a/vendor/github.com/rcrowley/go-metrics/meter.go b/vendor/github.com/rcrowley/go-metrics/meter.go new file mode 100644 index 00000000..0389ab0b --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/meter.go @@ -0,0 +1,233 @@ +package metrics + +import ( + "sync" + "time" +) + +// Meters count events to produce exponentially-weighted moving average rates +// at one-, five-, and fifteen-minutes and a mean rate. +type Meter interface { + Count() int64 + Mark(int64) + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + Snapshot() Meter +} + +// GetOrRegisterMeter returns an existing Meter or constructs and registers a +// new StandardMeter. +func GetOrRegisterMeter(name string, r Registry) Meter { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewMeter).(Meter) +} + +// NewMeter constructs a new StandardMeter and launches a goroutine. +func NewMeter() Meter { + if UseNilMetrics { + return NilMeter{} + } + m := newStandardMeter() + arbiter.Lock() + defer arbiter.Unlock() + arbiter.meters = append(arbiter.meters, m) + if !arbiter.started { + arbiter.started = true + go arbiter.tick() + } + return m +} + +// NewMeter constructs and registers a new StandardMeter and launches a +// goroutine. +func NewRegisteredMeter(name string, r Registry) Meter { + c := NewMeter() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// MeterSnapshot is a read-only copy of another Meter. +type MeterSnapshot struct { + count int64 + rate1, rate5, rate15, rateMean float64 +} + +// Count returns the count of events at the time the snapshot was taken. +func (m *MeterSnapshot) Count() int64 { return m.count } + +// Mark panics. +func (*MeterSnapshot) Mark(n int64) { + panic("Mark called on a MeterSnapshot") +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (m *MeterSnapshot) Rate1() float64 { return m.rate1 } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (m *MeterSnapshot) Rate5() float64 { return m.rate5 } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (m *MeterSnapshot) Rate15() float64 { return m.rate15 } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (m *MeterSnapshot) RateMean() float64 { return m.rateMean } + +// Snapshot returns the snapshot. +func (m *MeterSnapshot) Snapshot() Meter { return m } + +// NilMeter is a no-op Meter. +type NilMeter struct{} + +// Count is a no-op. +func (NilMeter) Count() int64 { return 0 } + +// Mark is a no-op. +func (NilMeter) Mark(n int64) {} + +// Rate1 is a no-op. +func (NilMeter) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilMeter) Rate5() float64 { return 0.0 } + +// Rate15is a no-op. +func (NilMeter) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilMeter) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilMeter) Snapshot() Meter { return NilMeter{} } + +// StandardMeter is the standard implementation of a Meter. +type StandardMeter struct { + lock sync.RWMutex + snapshot *MeterSnapshot + a1, a5, a15 EWMA + startTime time.Time +} + +func newStandardMeter() *StandardMeter { + return &StandardMeter{ + snapshot: &MeterSnapshot{}, + a1: NewEWMA1(), + a5: NewEWMA5(), + a15: NewEWMA15(), + startTime: time.Now(), + } +} + +// Count returns the number of events recorded. +func (m *StandardMeter) Count() int64 { + m.lock.RLock() + count := m.snapshot.count + m.lock.RUnlock() + return count +} + +// Mark records the occurance of n events. +func (m *StandardMeter) Mark(n int64) { + m.lock.Lock() + defer m.lock.Unlock() + m.snapshot.count += n + m.a1.Update(n) + m.a5.Update(n) + m.a15.Update(n) + m.updateSnapshot() +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (m *StandardMeter) Rate1() float64 { + m.lock.RLock() + rate1 := m.snapshot.rate1 + m.lock.RUnlock() + return rate1 +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (m *StandardMeter) Rate5() float64 { + m.lock.RLock() + rate5 := m.snapshot.rate5 + m.lock.RUnlock() + return rate5 +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (m *StandardMeter) Rate15() float64 { + m.lock.RLock() + rate15 := m.snapshot.rate15 + m.lock.RUnlock() + return rate15 +} + +// RateMean returns the meter's mean rate of events per second. +func (m *StandardMeter) RateMean() float64 { + m.lock.RLock() + rateMean := m.snapshot.rateMean + m.lock.RUnlock() + return rateMean +} + +// Snapshot returns a read-only copy of the meter. +func (m *StandardMeter) Snapshot() Meter { + m.lock.RLock() + snapshot := *m.snapshot + m.lock.RUnlock() + return &snapshot +} + +func (m *StandardMeter) updateSnapshot() { + // should run with write lock held on m.lock + snapshot := m.snapshot + snapshot.rate1 = m.a1.Rate() + snapshot.rate5 = m.a5.Rate() + snapshot.rate15 = m.a15.Rate() + snapshot.rateMean = float64(snapshot.count) / time.Since(m.startTime).Seconds() +} + +func (m *StandardMeter) tick() { + m.lock.Lock() + defer m.lock.Unlock() + m.a1.Tick() + m.a5.Tick() + m.a15.Tick() + m.updateSnapshot() +} + +type meterArbiter struct { + sync.RWMutex + started bool + meters []*StandardMeter + ticker *time.Ticker +} + +var arbiter = meterArbiter{ticker: time.NewTicker(5e9)} + +// Ticks meters on the scheduled interval +func (ma *meterArbiter) tick() { + for { + select { + case <-ma.ticker.C: + ma.tickMeters() + } + } +} + +func (ma *meterArbiter) tickMeters() { + ma.RLock() + defer ma.RUnlock() + for _, meter := range ma.meters { + meter.tick() + } +} diff --git a/vendor/github.com/rcrowley/go-metrics/metrics.go b/vendor/github.com/rcrowley/go-metrics/metrics.go new file mode 100644 index 00000000..b97a49ed --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/metrics.go @@ -0,0 +1,13 @@ +// Go port of Coda Hale's Metrics library +// +// +// +// Coda Hale's original work: +package metrics + +// UseNilMetrics is checked by the constructor functions for all of the +// standard metrics. If it is true, the metric returned is a stub. +// +// This global kill-switch helps quantify the observer effect and makes +// for less cluttered pprof profiles. +var UseNilMetrics bool = false diff --git a/vendor/github.com/rcrowley/go-metrics/opentsdb.go b/vendor/github.com/rcrowley/go-metrics/opentsdb.go new file mode 100644 index 00000000..266b6c93 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/opentsdb.go @@ -0,0 +1,119 @@ +package metrics + +import ( + "bufio" + "fmt" + "log" + "net" + "os" + "strings" + "time" +) + +var shortHostName string = "" + +// OpenTSDBConfig provides a container with configuration parameters for +// the OpenTSDB exporter +type OpenTSDBConfig struct { + Addr *net.TCPAddr // Network address to connect to + Registry Registry // Registry to be exported + FlushInterval time.Duration // Flush interval + DurationUnit time.Duration // Time conversion unit for durations + Prefix string // Prefix to be prepended to metric names +} + +// OpenTSDB is a blocking exporter function which reports metrics in r +// to a TSDB server located at addr, flushing them every d duration +// and prepending metric names with prefix. +func OpenTSDB(r Registry, d time.Duration, prefix string, addr *net.TCPAddr) { + OpenTSDBWithConfig(OpenTSDBConfig{ + Addr: addr, + Registry: r, + FlushInterval: d, + DurationUnit: time.Nanosecond, + Prefix: prefix, + }) +} + +// OpenTSDBWithConfig is a blocking exporter function just like OpenTSDB, +// but it takes a OpenTSDBConfig instead. +func OpenTSDBWithConfig(c OpenTSDBConfig) { + for _ = range time.Tick(c.FlushInterval) { + if err := openTSDB(&c); nil != err { + log.Println(err) + } + } +} + +func getShortHostname() string { + if shortHostName == "" { + host, _ := os.Hostname() + if index := strings.Index(host, "."); index > 0 { + shortHostName = host[:index] + } else { + shortHostName = host + } + } + return shortHostName +} + +func openTSDB(c *OpenTSDBConfig) error { + shortHostname := getShortHostname() + now := time.Now().Unix() + du := float64(c.DurationUnit) + conn, err := net.DialTCP("tcp", nil, c.Addr) + if nil != err { + return err + } + defer conn.Close() + w := bufio.NewWriter(conn) + c.Registry.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, metric.Count(), shortHostname) + case Gauge: + fmt.Fprintf(w, "put %s.%s.value %d %d host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + case GaugeFloat64: + fmt.Fprintf(w, "put %s.%s.value %d %f host=%s\n", c.Prefix, name, now, metric.Value(), shortHostname) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, h.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, h.Min(), shortHostname) + fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, h.Max(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, h.Mean(), shortHostname) + fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, h.StdDev(), shortHostname) + fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0], shortHostname) + fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1], shortHostname) + fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2], shortHostname) + fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3], shortHostname) + fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4], shortHostname) + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, m.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate1(), shortHostname) + fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate5(), shortHostname) + fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, m.Rate15(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, m.RateMean(), shortHostname) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "put %s.%s.count %d %d host=%s\n", c.Prefix, name, now, t.Count(), shortHostname) + fmt.Fprintf(w, "put %s.%s.min %d %d host=%s\n", c.Prefix, name, now, t.Min()/int64(du), shortHostname) + fmt.Fprintf(w, "put %s.%s.max %d %d host=%s\n", c.Prefix, name, now, t.Max()/int64(du), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean %d %.2f host=%s\n", c.Prefix, name, now, t.Mean()/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.std-dev %d %.2f host=%s\n", c.Prefix, name, now, t.StdDev()/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.50-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[0]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.75-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[1]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.95-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[2]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.99-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[3]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.999-percentile %d %.2f host=%s\n", c.Prefix, name, now, ps[4]/du, shortHostname) + fmt.Fprintf(w, "put %s.%s.one-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate1(), shortHostname) + fmt.Fprintf(w, "put %s.%s.five-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate5(), shortHostname) + fmt.Fprintf(w, "put %s.%s.fifteen-minute %d %.2f host=%s\n", c.Prefix, name, now, t.Rate15(), shortHostname) + fmt.Fprintf(w, "put %s.%s.mean-rate %d %.2f host=%s\n", c.Prefix, name, now, t.RateMean(), shortHostname) + } + w.Flush() + }) + return nil +} diff --git a/vendor/github.com/rcrowley/go-metrics/registry.go b/vendor/github.com/rcrowley/go-metrics/registry.go new file mode 100644 index 00000000..2bb7a1e7 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/registry.go @@ -0,0 +1,270 @@ +package metrics + +import ( + "fmt" + "reflect" + "strings" + "sync" +) + +// DuplicateMetric is the error returned by Registry.Register when a metric +// already exists. If you mean to Register that metric you must first +// Unregister the existing metric. +type DuplicateMetric string + +func (err DuplicateMetric) Error() string { + return fmt.Sprintf("duplicate metric: %s", string(err)) +} + +// A Registry holds references to a set of metrics by name and can iterate +// over them, calling callback functions provided by the user. +// +// This is an interface so as to encourage other structs to implement +// the Registry API as appropriate. +type Registry interface { + + // Call the given function for each registered metric. + Each(func(string, interface{})) + + // Get the metric by the given name or nil if none is registered. + Get(string) interface{} + + // Gets an existing metric or registers the given one. + // The interface can be the metric to register if not found in registry, + // or a function returning the metric for lazy instantiation. + GetOrRegister(string, interface{}) interface{} + + // Register the given metric under the given name. + Register(string, interface{}) error + + // Run all registered healthchecks. + RunHealthchecks() + + // Unregister the metric with the given name. + Unregister(string) + + // Unregister all metrics. (Mostly for testing.) + UnregisterAll() +} + +// The standard implementation of a Registry is a mutex-protected map +// of names to metrics. +type StandardRegistry struct { + metrics map[string]interface{} + mutex sync.Mutex +} + +// Create a new registry. +func NewRegistry() Registry { + return &StandardRegistry{metrics: make(map[string]interface{})} +} + +// Call the given function for each registered metric. +func (r *StandardRegistry) Each(f func(string, interface{})) { + for name, i := range r.registered() { + f(name, i) + } +} + +// Get the metric by the given name or nil if none is registered. +func (r *StandardRegistry) Get(name string) interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + return r.metrics[name] +} + +// Gets an existing metric or creates and registers a new one. Threadsafe +// alternative to calling Get and Register on failure. +// The interface can be the metric to register if not found in registry, +// or a function returning the metric for lazy instantiation. +func (r *StandardRegistry) GetOrRegister(name string, i interface{}) interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + if metric, ok := r.metrics[name]; ok { + return metric + } + if v := reflect.ValueOf(i); v.Kind() == reflect.Func { + i = v.Call(nil)[0].Interface() + } + r.register(name, i) + return i +} + +// Register the given metric under the given name. Returns a DuplicateMetric +// if a metric by the given name is already registered. +func (r *StandardRegistry) Register(name string, i interface{}) error { + r.mutex.Lock() + defer r.mutex.Unlock() + return r.register(name, i) +} + +// Run all registered healthchecks. +func (r *StandardRegistry) RunHealthchecks() { + r.mutex.Lock() + defer r.mutex.Unlock() + for _, i := range r.metrics { + if h, ok := i.(Healthcheck); ok { + h.Check() + } + } +} + +// Unregister the metric with the given name. +func (r *StandardRegistry) Unregister(name string) { + r.mutex.Lock() + defer r.mutex.Unlock() + delete(r.metrics, name) +} + +// Unregister all metrics. (Mostly for testing.) +func (r *StandardRegistry) UnregisterAll() { + r.mutex.Lock() + defer r.mutex.Unlock() + for name, _ := range r.metrics { + delete(r.metrics, name) + } +} + +func (r *StandardRegistry) register(name string, i interface{}) error { + if _, ok := r.metrics[name]; ok { + return DuplicateMetric(name) + } + switch i.(type) { + case Counter, Gauge, GaugeFloat64, Healthcheck, Histogram, Meter, Timer: + r.metrics[name] = i + } + return nil +} + +func (r *StandardRegistry) registered() map[string]interface{} { + r.mutex.Lock() + defer r.mutex.Unlock() + metrics := make(map[string]interface{}, len(r.metrics)) + for name, i := range r.metrics { + metrics[name] = i + } + return metrics +} + +type PrefixedRegistry struct { + underlying Registry + prefix string +} + +func NewPrefixedRegistry(prefix string) Registry { + return &PrefixedRegistry{ + underlying: NewRegistry(), + prefix: prefix, + } +} + +func NewPrefixedChildRegistry(parent Registry, prefix string) Registry { + return &PrefixedRegistry{ + underlying: parent, + prefix: prefix, + } +} + +// Call the given function for each registered metric. +func (r *PrefixedRegistry) Each(fn func(string, interface{})) { + wrappedFn := func(prefix string) func(string, interface{}) { + return func(name string, iface interface{}) { + if strings.HasPrefix(name, prefix) { + fn(name, iface) + } else { + return + } + } + } + + baseRegistry, prefix := findPrefix(r, "") + baseRegistry.Each(wrappedFn(prefix)) +} + +func findPrefix(registry Registry, prefix string) (Registry, string) { + switch r := registry.(type) { + case *PrefixedRegistry: + return findPrefix(r.underlying, r.prefix+prefix) + case *StandardRegistry: + return r, prefix + } + return nil, "" +} + +// Get the metric by the given name or nil if none is registered. +func (r *PrefixedRegistry) Get(name string) interface{} { + realName := r.prefix + name + return r.underlying.Get(realName) +} + +// Gets an existing metric or registers the given one. +// The interface can be the metric to register if not found in registry, +// or a function returning the metric for lazy instantiation. +func (r *PrefixedRegistry) GetOrRegister(name string, metric interface{}) interface{} { + realName := r.prefix + name + return r.underlying.GetOrRegister(realName, metric) +} + +// Register the given metric under the given name. The name will be prefixed. +func (r *PrefixedRegistry) Register(name string, metric interface{}) error { + realName := r.prefix + name + return r.underlying.Register(realName, metric) +} + +// Run all registered healthchecks. +func (r *PrefixedRegistry) RunHealthchecks() { + r.underlying.RunHealthchecks() +} + +// Unregister the metric with the given name. The name will be prefixed. +func (r *PrefixedRegistry) Unregister(name string) { + realName := r.prefix + name + r.underlying.Unregister(realName) +} + +// Unregister all metrics. (Mostly for testing.) +func (r *PrefixedRegistry) UnregisterAll() { + r.underlying.UnregisterAll() +} + +var DefaultRegistry Registry = NewRegistry() + +// Call the given function for each registered metric. +func Each(f func(string, interface{})) { + DefaultRegistry.Each(f) +} + +// Get the metric by the given name or nil if none is registered. +func Get(name string) interface{} { + return DefaultRegistry.Get(name) +} + +// Gets an existing metric or creates and registers a new one. Threadsafe +// alternative to calling Get and Register on failure. +func GetOrRegister(name string, i interface{}) interface{} { + return DefaultRegistry.GetOrRegister(name, i) +} + +// Register the given metric under the given name. Returns a DuplicateMetric +// if a metric by the given name is already registered. +func Register(name string, i interface{}) error { + return DefaultRegistry.Register(name, i) +} + +// Register the given metric under the given name. Panics if a metric by the +// given name is already registered. +func MustRegister(name string, i interface{}) { + if err := Register(name, i); err != nil { + panic(err) + } +} + +// Run all registered healthchecks. +func RunHealthchecks() { + DefaultRegistry.RunHealthchecks() +} + +// Unregister the metric with the given name. +func Unregister(name string) { + DefaultRegistry.Unregister(name) +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime.go b/vendor/github.com/rcrowley/go-metrics/runtime.go new file mode 100644 index 00000000..11c6b785 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime.go @@ -0,0 +1,212 @@ +package metrics + +import ( + "runtime" + "runtime/pprof" + "time" +) + +var ( + memStats runtime.MemStats + runtimeMetrics struct { + MemStats struct { + Alloc Gauge + BuckHashSys Gauge + DebugGC Gauge + EnableGC Gauge + Frees Gauge + HeapAlloc Gauge + HeapIdle Gauge + HeapInuse Gauge + HeapObjects Gauge + HeapReleased Gauge + HeapSys Gauge + LastGC Gauge + Lookups Gauge + Mallocs Gauge + MCacheInuse Gauge + MCacheSys Gauge + MSpanInuse Gauge + MSpanSys Gauge + NextGC Gauge + NumGC Gauge + GCCPUFraction GaugeFloat64 + PauseNs Histogram + PauseTotalNs Gauge + StackInuse Gauge + StackSys Gauge + Sys Gauge + TotalAlloc Gauge + } + NumCgoCall Gauge + NumGoroutine Gauge + NumThread Gauge + ReadMemStats Timer + } + frees uint64 + lookups uint64 + mallocs uint64 + numGC uint32 + numCgoCalls int64 + + threadCreateProfile = pprof.Lookup("threadcreate") +) + +// Capture new values for the Go runtime statistics exported in +// runtime.MemStats. This is designed to be called as a goroutine. +func CaptureRuntimeMemStats(r Registry, d time.Duration) { + for _ = range time.Tick(d) { + CaptureRuntimeMemStatsOnce(r) + } +} + +// Capture new values for the Go runtime statistics exported in +// runtime.MemStats. This is designed to be called in a background +// goroutine. Giving a registry which has not been given to +// RegisterRuntimeMemStats will panic. +// +// Be very careful with this because runtime.ReadMemStats calls the C +// functions runtime·semacquire(&runtime·worldsema) and runtime·stoptheworld() +// and that last one does what it says on the tin. +func CaptureRuntimeMemStatsOnce(r Registry) { + t := time.Now() + runtime.ReadMemStats(&memStats) // This takes 50-200us. + runtimeMetrics.ReadMemStats.UpdateSince(t) + + runtimeMetrics.MemStats.Alloc.Update(int64(memStats.Alloc)) + runtimeMetrics.MemStats.BuckHashSys.Update(int64(memStats.BuckHashSys)) + if memStats.DebugGC { + runtimeMetrics.MemStats.DebugGC.Update(1) + } else { + runtimeMetrics.MemStats.DebugGC.Update(0) + } + if memStats.EnableGC { + runtimeMetrics.MemStats.EnableGC.Update(1) + } else { + runtimeMetrics.MemStats.EnableGC.Update(0) + } + + runtimeMetrics.MemStats.Frees.Update(int64(memStats.Frees - frees)) + runtimeMetrics.MemStats.HeapAlloc.Update(int64(memStats.HeapAlloc)) + runtimeMetrics.MemStats.HeapIdle.Update(int64(memStats.HeapIdle)) + runtimeMetrics.MemStats.HeapInuse.Update(int64(memStats.HeapInuse)) + runtimeMetrics.MemStats.HeapObjects.Update(int64(memStats.HeapObjects)) + runtimeMetrics.MemStats.HeapReleased.Update(int64(memStats.HeapReleased)) + runtimeMetrics.MemStats.HeapSys.Update(int64(memStats.HeapSys)) + runtimeMetrics.MemStats.LastGC.Update(int64(memStats.LastGC)) + runtimeMetrics.MemStats.Lookups.Update(int64(memStats.Lookups - lookups)) + runtimeMetrics.MemStats.Mallocs.Update(int64(memStats.Mallocs - mallocs)) + runtimeMetrics.MemStats.MCacheInuse.Update(int64(memStats.MCacheInuse)) + runtimeMetrics.MemStats.MCacheSys.Update(int64(memStats.MCacheSys)) + runtimeMetrics.MemStats.MSpanInuse.Update(int64(memStats.MSpanInuse)) + runtimeMetrics.MemStats.MSpanSys.Update(int64(memStats.MSpanSys)) + runtimeMetrics.MemStats.NextGC.Update(int64(memStats.NextGC)) + runtimeMetrics.MemStats.NumGC.Update(int64(memStats.NumGC - numGC)) + runtimeMetrics.MemStats.GCCPUFraction.Update(gcCPUFraction(&memStats)) + + // + i := numGC % uint32(len(memStats.PauseNs)) + ii := memStats.NumGC % uint32(len(memStats.PauseNs)) + if memStats.NumGC-numGC >= uint32(len(memStats.PauseNs)) { + for i = 0; i < uint32(len(memStats.PauseNs)); i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + } else { + if i > ii { + for ; i < uint32(len(memStats.PauseNs)); i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + i = 0 + } + for ; i < ii; i++ { + runtimeMetrics.MemStats.PauseNs.Update(int64(memStats.PauseNs[i])) + } + } + frees = memStats.Frees + lookups = memStats.Lookups + mallocs = memStats.Mallocs + numGC = memStats.NumGC + + runtimeMetrics.MemStats.PauseTotalNs.Update(int64(memStats.PauseTotalNs)) + runtimeMetrics.MemStats.StackInuse.Update(int64(memStats.StackInuse)) + runtimeMetrics.MemStats.StackSys.Update(int64(memStats.StackSys)) + runtimeMetrics.MemStats.Sys.Update(int64(memStats.Sys)) + runtimeMetrics.MemStats.TotalAlloc.Update(int64(memStats.TotalAlloc)) + + currentNumCgoCalls := numCgoCall() + runtimeMetrics.NumCgoCall.Update(currentNumCgoCalls - numCgoCalls) + numCgoCalls = currentNumCgoCalls + + runtimeMetrics.NumGoroutine.Update(int64(runtime.NumGoroutine())) + + runtimeMetrics.NumThread.Update(int64(threadCreateProfile.Count())) +} + +// Register runtimeMetrics for the Go runtime statistics exported in runtime and +// specifically runtime.MemStats. The runtimeMetrics are named by their +// fully-qualified Go symbols, i.e. runtime.MemStats.Alloc. +func RegisterRuntimeMemStats(r Registry) { + runtimeMetrics.MemStats.Alloc = NewGauge() + runtimeMetrics.MemStats.BuckHashSys = NewGauge() + runtimeMetrics.MemStats.DebugGC = NewGauge() + runtimeMetrics.MemStats.EnableGC = NewGauge() + runtimeMetrics.MemStats.Frees = NewGauge() + runtimeMetrics.MemStats.HeapAlloc = NewGauge() + runtimeMetrics.MemStats.HeapIdle = NewGauge() + runtimeMetrics.MemStats.HeapInuse = NewGauge() + runtimeMetrics.MemStats.HeapObjects = NewGauge() + runtimeMetrics.MemStats.HeapReleased = NewGauge() + runtimeMetrics.MemStats.HeapSys = NewGauge() + runtimeMetrics.MemStats.LastGC = NewGauge() + runtimeMetrics.MemStats.Lookups = NewGauge() + runtimeMetrics.MemStats.Mallocs = NewGauge() + runtimeMetrics.MemStats.MCacheInuse = NewGauge() + runtimeMetrics.MemStats.MCacheSys = NewGauge() + runtimeMetrics.MemStats.MSpanInuse = NewGauge() + runtimeMetrics.MemStats.MSpanSys = NewGauge() + runtimeMetrics.MemStats.NextGC = NewGauge() + runtimeMetrics.MemStats.NumGC = NewGauge() + runtimeMetrics.MemStats.GCCPUFraction = NewGaugeFloat64() + runtimeMetrics.MemStats.PauseNs = NewHistogram(NewExpDecaySample(1028, 0.015)) + runtimeMetrics.MemStats.PauseTotalNs = NewGauge() + runtimeMetrics.MemStats.StackInuse = NewGauge() + runtimeMetrics.MemStats.StackSys = NewGauge() + runtimeMetrics.MemStats.Sys = NewGauge() + runtimeMetrics.MemStats.TotalAlloc = NewGauge() + runtimeMetrics.NumCgoCall = NewGauge() + runtimeMetrics.NumGoroutine = NewGauge() + runtimeMetrics.NumThread = NewGauge() + runtimeMetrics.ReadMemStats = NewTimer() + + r.Register("runtime.MemStats.Alloc", runtimeMetrics.MemStats.Alloc) + r.Register("runtime.MemStats.BuckHashSys", runtimeMetrics.MemStats.BuckHashSys) + r.Register("runtime.MemStats.DebugGC", runtimeMetrics.MemStats.DebugGC) + r.Register("runtime.MemStats.EnableGC", runtimeMetrics.MemStats.EnableGC) + r.Register("runtime.MemStats.Frees", runtimeMetrics.MemStats.Frees) + r.Register("runtime.MemStats.HeapAlloc", runtimeMetrics.MemStats.HeapAlloc) + r.Register("runtime.MemStats.HeapIdle", runtimeMetrics.MemStats.HeapIdle) + r.Register("runtime.MemStats.HeapInuse", runtimeMetrics.MemStats.HeapInuse) + r.Register("runtime.MemStats.HeapObjects", runtimeMetrics.MemStats.HeapObjects) + r.Register("runtime.MemStats.HeapReleased", runtimeMetrics.MemStats.HeapReleased) + r.Register("runtime.MemStats.HeapSys", runtimeMetrics.MemStats.HeapSys) + r.Register("runtime.MemStats.LastGC", runtimeMetrics.MemStats.LastGC) + r.Register("runtime.MemStats.Lookups", runtimeMetrics.MemStats.Lookups) + r.Register("runtime.MemStats.Mallocs", runtimeMetrics.MemStats.Mallocs) + r.Register("runtime.MemStats.MCacheInuse", runtimeMetrics.MemStats.MCacheInuse) + r.Register("runtime.MemStats.MCacheSys", runtimeMetrics.MemStats.MCacheSys) + r.Register("runtime.MemStats.MSpanInuse", runtimeMetrics.MemStats.MSpanInuse) + r.Register("runtime.MemStats.MSpanSys", runtimeMetrics.MemStats.MSpanSys) + r.Register("runtime.MemStats.NextGC", runtimeMetrics.MemStats.NextGC) + r.Register("runtime.MemStats.NumGC", runtimeMetrics.MemStats.NumGC) + r.Register("runtime.MemStats.GCCPUFraction", runtimeMetrics.MemStats.GCCPUFraction) + r.Register("runtime.MemStats.PauseNs", runtimeMetrics.MemStats.PauseNs) + r.Register("runtime.MemStats.PauseTotalNs", runtimeMetrics.MemStats.PauseTotalNs) + r.Register("runtime.MemStats.StackInuse", runtimeMetrics.MemStats.StackInuse) + r.Register("runtime.MemStats.StackSys", runtimeMetrics.MemStats.StackSys) + r.Register("runtime.MemStats.Sys", runtimeMetrics.MemStats.Sys) + r.Register("runtime.MemStats.TotalAlloc", runtimeMetrics.MemStats.TotalAlloc) + r.Register("runtime.NumCgoCall", runtimeMetrics.NumCgoCall) + r.Register("runtime.NumGoroutine", runtimeMetrics.NumGoroutine) + r.Register("runtime.NumThread", runtimeMetrics.NumThread) + r.Register("runtime.ReadMemStats", runtimeMetrics.ReadMemStats) +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime_cgo.go b/vendor/github.com/rcrowley/go-metrics/runtime_cgo.go new file mode 100644 index 00000000..e3391f4e --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime_cgo.go @@ -0,0 +1,10 @@ +// +build cgo +// +build !appengine + +package metrics + +import "runtime" + +func numCgoCall() int64 { + return runtime.NumCgoCall() +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime_gccpufraction.go b/vendor/github.com/rcrowley/go-metrics/runtime_gccpufraction.go new file mode 100644 index 00000000..ca12c05b --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime_gccpufraction.go @@ -0,0 +1,9 @@ +// +build go1.5 + +package metrics + +import "runtime" + +func gcCPUFraction(memStats *runtime.MemStats) float64 { + return memStats.GCCPUFraction +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime_no_cgo.go b/vendor/github.com/rcrowley/go-metrics/runtime_no_cgo.go new file mode 100644 index 00000000..616a3b47 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime_no_cgo.go @@ -0,0 +1,7 @@ +// +build !cgo appengine + +package metrics + +func numCgoCall() int64 { + return 0 +} diff --git a/vendor/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go b/vendor/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go new file mode 100644 index 00000000..be96aa6f --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/runtime_no_gccpufraction.go @@ -0,0 +1,9 @@ +// +build !go1.5 + +package metrics + +import "runtime" + +func gcCPUFraction(memStats *runtime.MemStats) float64 { + return 0 +} diff --git a/vendor/github.com/rcrowley/go-metrics/sample.go b/vendor/github.com/rcrowley/go-metrics/sample.go new file mode 100644 index 00000000..fecee5ef --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/sample.go @@ -0,0 +1,616 @@ +package metrics + +import ( + "math" + "math/rand" + "sort" + "sync" + "time" +) + +const rescaleThreshold = time.Hour + +// Samples maintain a statistically-significant selection of values from +// a stream. +type Sample interface { + Clear() + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Size() int + Snapshot() Sample + StdDev() float64 + Sum() int64 + Update(int64) + Values() []int64 + Variance() float64 +} + +// ExpDecaySample is an exponentially-decaying sample using a forward-decaying +// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time +// Decay Model for Streaming Systems". +// +// +type ExpDecaySample struct { + alpha float64 + count int64 + mutex sync.Mutex + reservoirSize int + t0, t1 time.Time + values *expDecaySampleHeap +} + +// NewExpDecaySample constructs a new exponentially-decaying sample with the +// given reservoir size and alpha. +func NewExpDecaySample(reservoirSize int, alpha float64) Sample { + if UseNilMetrics { + return NilSample{} + } + s := &ExpDecaySample{ + alpha: alpha, + reservoirSize: reservoirSize, + t0: time.Now(), + values: newExpDecaySampleHeap(reservoirSize), + } + s.t1 = s.t0.Add(rescaleThreshold) + return s +} + +// Clear clears all samples. +func (s *ExpDecaySample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.t0 = time.Now() + s.t1 = s.t0.Add(rescaleThreshold) + s.values.Clear() +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *ExpDecaySample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *ExpDecaySample) Max() int64 { + return SampleMax(s.Values()) +} + +// Mean returns the mean of the values in the sample. +func (s *ExpDecaySample) Mean() float64 { + return SampleMean(s.Values()) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *ExpDecaySample) Min() int64 { + return SampleMin(s.Values()) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *ExpDecaySample) Percentile(p float64) float64 { + return SamplePercentile(s.Values(), p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *ExpDecaySample) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.Values(), ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *ExpDecaySample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.values.Size() +} + +// Snapshot returns a read-only copy of the sample. +func (s *ExpDecaySample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *ExpDecaySample) StdDev() float64 { + return SampleStdDev(s.Values()) +} + +// Sum returns the sum of the values in the sample. +func (s *ExpDecaySample) Sum() int64 { + return SampleSum(s.Values()) +} + +// Update samples a new value. +func (s *ExpDecaySample) Update(v int64) { + s.update(time.Now(), v) +} + +// Values returns a copy of the values in the sample. +func (s *ExpDecaySample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + vals := s.values.Values() + values := make([]int64, len(vals)) + for i, v := range vals { + values[i] = v.v + } + return values +} + +// Variance returns the variance of the values in the sample. +func (s *ExpDecaySample) Variance() float64 { + return SampleVariance(s.Values()) +} + +// update samples a new value at a particular timestamp. This is a method all +// its own to facilitate testing. +func (s *ExpDecaySample) update(t time.Time, v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if s.values.Size() == s.reservoirSize { + s.values.Pop() + } + s.values.Push(expDecaySample{ + k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(), + v: v, + }) + if t.After(s.t1) { + values := s.values.Values() + t0 := s.t0 + s.values.Clear() + s.t0 = t + s.t1 = s.t0.Add(rescaleThreshold) + for _, v := range values { + v.k = v.k * math.Exp(-s.alpha*s.t0.Sub(t0).Seconds()) + s.values.Push(v) + } + } +} + +// NilSample is a no-op Sample. +type NilSample struct{} + +// Clear is a no-op. +func (NilSample) Clear() {} + +// Count is a no-op. +func (NilSample) Count() int64 { return 0 } + +// Max is a no-op. +func (NilSample) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilSample) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilSample) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilSample) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilSample) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Size is a no-op. +func (NilSample) Size() int { return 0 } + +// Sample is a no-op. +func (NilSample) Snapshot() Sample { return NilSample{} } + +// StdDev is a no-op. +func (NilSample) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilSample) Sum() int64 { return 0 } + +// Update is a no-op. +func (NilSample) Update(v int64) {} + +// Values is a no-op. +func (NilSample) Values() []int64 { return []int64{} } + +// Variance is a no-op. +func (NilSample) Variance() float64 { return 0.0 } + +// SampleMax returns the maximum value of the slice of int64. +func SampleMax(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var max int64 = math.MinInt64 + for _, v := range values { + if max < v { + max = v + } + } + return max +} + +// SampleMean returns the mean value of the slice of int64. +func SampleMean(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + return float64(SampleSum(values)) / float64(len(values)) +} + +// SampleMin returns the minimum value of the slice of int64. +func SampleMin(values []int64) int64 { + if 0 == len(values) { + return 0 + } + var min int64 = math.MaxInt64 + for _, v := range values { + if min > v { + min = v + } + } + return min +} + +// SamplePercentiles returns an arbitrary percentile of the slice of int64. +func SamplePercentile(values int64Slice, p float64) float64 { + return SamplePercentiles(values, []float64{p})[0] +} + +// SamplePercentiles returns a slice of arbitrary percentiles of the slice of +// int64. +func SamplePercentiles(values int64Slice, ps []float64) []float64 { + scores := make([]float64, len(ps)) + size := len(values) + if size > 0 { + sort.Sort(values) + for i, p := range ps { + pos := p * float64(size+1) + if pos < 1.0 { + scores[i] = float64(values[0]) + } else if pos >= float64(size) { + scores[i] = float64(values[size-1]) + } else { + lower := float64(values[int(pos)-1]) + upper := float64(values[int(pos)]) + scores[i] = lower + (pos-math.Floor(pos))*(upper-lower) + } + } + } + return scores +} + +// SampleSnapshot is a read-only copy of another Sample. +type SampleSnapshot struct { + count int64 + values []int64 +} + +func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot { + return &SampleSnapshot{ + count: count, + values: values, + } +} + +// Clear panics. +func (*SampleSnapshot) Clear() { + panic("Clear called on a SampleSnapshot") +} + +// Count returns the count of inputs at the time the snapshot was taken. +func (s *SampleSnapshot) Count() int64 { return s.count } + +// Max returns the maximal value at the time the snapshot was taken. +func (s *SampleSnapshot) Max() int64 { return SampleMax(s.values) } + +// Mean returns the mean value at the time the snapshot was taken. +func (s *SampleSnapshot) Mean() float64 { return SampleMean(s.values) } + +// Min returns the minimal value at the time the snapshot was taken. +func (s *SampleSnapshot) Min() int64 { return SampleMin(s.values) } + +// Percentile returns an arbitrary percentile of values at the time the +// snapshot was taken. +func (s *SampleSnapshot) Percentile(p float64) float64 { + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values at the time +// the snapshot was taken. +func (s *SampleSnapshot) Percentiles(ps []float64) []float64 { + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample at the time the snapshot was taken. +func (s *SampleSnapshot) Size() int { return len(s.values) } + +// Snapshot returns the snapshot. +func (s *SampleSnapshot) Snapshot() Sample { return s } + +// StdDev returns the standard deviation of values at the time the snapshot was +// taken. +func (s *SampleSnapshot) StdDev() float64 { return SampleStdDev(s.values) } + +// Sum returns the sum of values at the time the snapshot was taken. +func (s *SampleSnapshot) Sum() int64 { return SampleSum(s.values) } + +// Update panics. +func (*SampleSnapshot) Update(int64) { + panic("Update called on a SampleSnapshot") +} + +// Values returns a copy of the values in the sample. +func (s *SampleSnapshot) Values() []int64 { + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of values at the time the snapshot was taken. +func (s *SampleSnapshot) Variance() float64 { return SampleVariance(s.values) } + +// SampleStdDev returns the standard deviation of the slice of int64. +func SampleStdDev(values []int64) float64 { + return math.Sqrt(SampleVariance(values)) +} + +// SampleSum returns the sum of the slice of int64. +func SampleSum(values []int64) int64 { + var sum int64 + for _, v := range values { + sum += v + } + return sum +} + +// SampleVariance returns the variance of the slice of int64. +func SampleVariance(values []int64) float64 { + if 0 == len(values) { + return 0.0 + } + m := SampleMean(values) + var sum float64 + for _, v := range values { + d := float64(v) - m + sum += d * d + } + return sum / float64(len(values)) +} + +// A uniform sample using Vitter's Algorithm R. +// +// +type UniformSample struct { + count int64 + mutex sync.Mutex + reservoirSize int + values []int64 +} + +// NewUniformSample constructs a new uniform sample with the given reservoir +// size. +func NewUniformSample(reservoirSize int) Sample { + if UseNilMetrics { + return NilSample{} + } + return &UniformSample{ + reservoirSize: reservoirSize, + values: make([]int64, 0, reservoirSize), + } +} + +// Clear clears all samples. +func (s *UniformSample) Clear() { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count = 0 + s.values = make([]int64, 0, s.reservoirSize) +} + +// Count returns the number of samples recorded, which may exceed the +// reservoir size. +func (s *UniformSample) Count() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return s.count +} + +// Max returns the maximum value in the sample, which may not be the maximum +// value ever to be part of the sample. +func (s *UniformSample) Max() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMax(s.values) +} + +// Mean returns the mean of the values in the sample. +func (s *UniformSample) Mean() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMean(s.values) +} + +// Min returns the minimum value in the sample, which may not be the minimum +// value ever to be part of the sample. +func (s *UniformSample) Min() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleMin(s.values) +} + +// Percentile returns an arbitrary percentile of values in the sample. +func (s *UniformSample) Percentile(p float64) float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentile(s.values, p) +} + +// Percentiles returns a slice of arbitrary percentiles of values in the +// sample. +func (s *UniformSample) Percentiles(ps []float64) []float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SamplePercentiles(s.values, ps) +} + +// Size returns the size of the sample, which is at most the reservoir size. +func (s *UniformSample) Size() int { + s.mutex.Lock() + defer s.mutex.Unlock() + return len(s.values) +} + +// Snapshot returns a read-only copy of the sample. +func (s *UniformSample) Snapshot() Sample { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return &SampleSnapshot{ + count: s.count, + values: values, + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (s *UniformSample) StdDev() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleStdDev(s.values) +} + +// Sum returns the sum of the values in the sample. +func (s *UniformSample) Sum() int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleSum(s.values) +} + +// Update samples a new value. +func (s *UniformSample) Update(v int64) { + s.mutex.Lock() + defer s.mutex.Unlock() + s.count++ + if len(s.values) < s.reservoirSize { + s.values = append(s.values, v) + } else { + r := rand.Int63n(s.count) + if r < int64(len(s.values)) { + s.values[int(r)] = v + } + } +} + +// Values returns a copy of the values in the sample. +func (s *UniformSample) Values() []int64 { + s.mutex.Lock() + defer s.mutex.Unlock() + values := make([]int64, len(s.values)) + copy(values, s.values) + return values +} + +// Variance returns the variance of the values in the sample. +func (s *UniformSample) Variance() float64 { + s.mutex.Lock() + defer s.mutex.Unlock() + return SampleVariance(s.values) +} + +// expDecaySample represents an individual sample in a heap. +type expDecaySample struct { + k float64 + v int64 +} + +func newExpDecaySampleHeap(reservoirSize int) *expDecaySampleHeap { + return &expDecaySampleHeap{make([]expDecaySample, 0, reservoirSize)} +} + +// expDecaySampleHeap is a min-heap of expDecaySamples. +// The internal implementation is copied from the standard library's container/heap +type expDecaySampleHeap struct { + s []expDecaySample +} + +func (h *expDecaySampleHeap) Clear() { + h.s = h.s[:0] +} + +func (h *expDecaySampleHeap) Push(s expDecaySample) { + n := len(h.s) + h.s = h.s[0 : n+1] + h.s[n] = s + h.up(n) +} + +func (h *expDecaySampleHeap) Pop() expDecaySample { + n := len(h.s) - 1 + h.s[0], h.s[n] = h.s[n], h.s[0] + h.down(0, n) + + n = len(h.s) + s := h.s[n-1] + h.s = h.s[0 : n-1] + return s +} + +func (h *expDecaySampleHeap) Size() int { + return len(h.s) +} + +func (h *expDecaySampleHeap) Values() []expDecaySample { + return h.s +} + +func (h *expDecaySampleHeap) up(j int) { + for { + i := (j - 1) / 2 // parent + if i == j || !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + j = i + } +} + +func (h *expDecaySampleHeap) down(i, n int) { + for { + j1 := 2*i + 1 + if j1 >= n || j1 < 0 { // j1 < 0 after int overflow + break + } + j := j1 // left child + if j2 := j1 + 1; j2 < n && !(h.s[j1].k < h.s[j2].k) { + j = j2 // = 2*i + 2 // right child + } + if !(h.s[j].k < h.s[i].k) { + break + } + h.s[i], h.s[j] = h.s[j], h.s[i] + i = j + } +} + +type int64Slice []int64 + +func (p int64Slice) Len() int { return len(p) } +func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] } +func (p int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } diff --git a/vendor/github.com/rcrowley/go-metrics/syslog.go b/vendor/github.com/rcrowley/go-metrics/syslog.go new file mode 100644 index 00000000..693f1908 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/syslog.go @@ -0,0 +1,78 @@ +// +build !windows + +package metrics + +import ( + "fmt" + "log/syslog" + "time" +) + +// Output each metric in the given registry to syslog periodically using +// the given syslogger. +func Syslog(r Registry, d time.Duration, w *syslog.Writer) { + for _ = range time.Tick(d) { + r.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case Counter: + w.Info(fmt.Sprintf("counter %s: count: %d", name, metric.Count())) + case Gauge: + w.Info(fmt.Sprintf("gauge %s: value: %d", name, metric.Value())) + case GaugeFloat64: + w.Info(fmt.Sprintf("gauge %s: value: %f", name, metric.Value())) + case Healthcheck: + metric.Check() + w.Info(fmt.Sprintf("healthcheck %s: error: %v", name, metric.Error())) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + w.Info(fmt.Sprintf( + "histogram %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f", + name, + h.Count(), + h.Min(), + h.Max(), + h.Mean(), + h.StdDev(), + ps[0], + ps[1], + ps[2], + ps[3], + ps[4], + )) + case Meter: + m := metric.Snapshot() + w.Info(fmt.Sprintf( + "meter %s: count: %d 1-min: %.2f 5-min: %.2f 15-min: %.2f mean: %.2f", + name, + m.Count(), + m.Rate1(), + m.Rate5(), + m.Rate15(), + m.RateMean(), + )) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + w.Info(fmt.Sprintf( + "timer %s: count: %d min: %d max: %d mean: %.2f stddev: %.2f median: %.2f 75%%: %.2f 95%%: %.2f 99%%: %.2f 99.9%%: %.2f 1-min: %.2f 5-min: %.2f 15-min: %.2f mean-rate: %.2f", + name, + t.Count(), + t.Min(), + t.Max(), + t.Mean(), + t.StdDev(), + ps[0], + ps[1], + ps[2], + ps[3], + ps[4], + t.Rate1(), + t.Rate5(), + t.Rate15(), + t.RateMean(), + )) + } + }) + } +} diff --git a/vendor/github.com/rcrowley/go-metrics/timer.go b/vendor/github.com/rcrowley/go-metrics/timer.go new file mode 100644 index 00000000..17db8f8d --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/timer.go @@ -0,0 +1,311 @@ +package metrics + +import ( + "sync" + "time" +) + +// Timers capture the duration and rate of events. +type Timer interface { + Count() int64 + Max() int64 + Mean() float64 + Min() int64 + Percentile(float64) float64 + Percentiles([]float64) []float64 + Rate1() float64 + Rate5() float64 + Rate15() float64 + RateMean() float64 + Snapshot() Timer + StdDev() float64 + Sum() int64 + Time(func()) + Update(time.Duration) + UpdateSince(time.Time) + Variance() float64 +} + +// GetOrRegisterTimer returns an existing Timer or constructs and registers a +// new StandardTimer. +func GetOrRegisterTimer(name string, r Registry) Timer { + if nil == r { + r = DefaultRegistry + } + return r.GetOrRegister(name, NewTimer).(Timer) +} + +// NewCustomTimer constructs a new StandardTimer from a Histogram and a Meter. +func NewCustomTimer(h Histogram, m Meter) Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + histogram: h, + meter: m, + } +} + +// NewRegisteredTimer constructs and registers a new StandardTimer. +func NewRegisteredTimer(name string, r Registry) Timer { + c := NewTimer() + if nil == r { + r = DefaultRegistry + } + r.Register(name, c) + return c +} + +// NewTimer constructs a new StandardTimer using an exponentially-decaying +// sample with the same reservoir size and alpha as UNIX load averages. +func NewTimer() Timer { + if UseNilMetrics { + return NilTimer{} + } + return &StandardTimer{ + histogram: NewHistogram(NewExpDecaySample(1028, 0.015)), + meter: NewMeter(), + } +} + +// NilTimer is a no-op Timer. +type NilTimer struct { + h Histogram + m Meter +} + +// Count is a no-op. +func (NilTimer) Count() int64 { return 0 } + +// Max is a no-op. +func (NilTimer) Max() int64 { return 0 } + +// Mean is a no-op. +func (NilTimer) Mean() float64 { return 0.0 } + +// Min is a no-op. +func (NilTimer) Min() int64 { return 0 } + +// Percentile is a no-op. +func (NilTimer) Percentile(p float64) float64 { return 0.0 } + +// Percentiles is a no-op. +func (NilTimer) Percentiles(ps []float64) []float64 { + return make([]float64, len(ps)) +} + +// Rate1 is a no-op. +func (NilTimer) Rate1() float64 { return 0.0 } + +// Rate5 is a no-op. +func (NilTimer) Rate5() float64 { return 0.0 } + +// Rate15 is a no-op. +func (NilTimer) Rate15() float64 { return 0.0 } + +// RateMean is a no-op. +func (NilTimer) RateMean() float64 { return 0.0 } + +// Snapshot is a no-op. +func (NilTimer) Snapshot() Timer { return NilTimer{} } + +// StdDev is a no-op. +func (NilTimer) StdDev() float64 { return 0.0 } + +// Sum is a no-op. +func (NilTimer) Sum() int64 { return 0 } + +// Time is a no-op. +func (NilTimer) Time(func()) {} + +// Update is a no-op. +func (NilTimer) Update(time.Duration) {} + +// UpdateSince is a no-op. +func (NilTimer) UpdateSince(time.Time) {} + +// Variance is a no-op. +func (NilTimer) Variance() float64 { return 0.0 } + +// StandardTimer is the standard implementation of a Timer and uses a Histogram +// and Meter. +type StandardTimer struct { + histogram Histogram + meter Meter + mutex sync.Mutex +} + +// Count returns the number of events recorded. +func (t *StandardTimer) Count() int64 { + return t.histogram.Count() +} + +// Max returns the maximum value in the sample. +func (t *StandardTimer) Max() int64 { + return t.histogram.Max() +} + +// Mean returns the mean of the values in the sample. +func (t *StandardTimer) Mean() float64 { + return t.histogram.Mean() +} + +// Min returns the minimum value in the sample. +func (t *StandardTimer) Min() int64 { + return t.histogram.Min() +} + +// Percentile returns an arbitrary percentile of the values in the sample. +func (t *StandardTimer) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of the values in the +// sample. +func (t *StandardTimer) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second. +func (t *StandardTimer) Rate1() float64 { + return t.meter.Rate1() +} + +// Rate5 returns the five-minute moving average rate of events per second. +func (t *StandardTimer) Rate5() float64 { + return t.meter.Rate5() +} + +// Rate15 returns the fifteen-minute moving average rate of events per second. +func (t *StandardTimer) Rate15() float64 { + return t.meter.Rate15() +} + +// RateMean returns the meter's mean rate of events per second. +func (t *StandardTimer) RateMean() float64 { + return t.meter.RateMean() +} + +// Snapshot returns a read-only copy of the timer. +func (t *StandardTimer) Snapshot() Timer { + t.mutex.Lock() + defer t.mutex.Unlock() + return &TimerSnapshot{ + histogram: t.histogram.Snapshot().(*HistogramSnapshot), + meter: t.meter.Snapshot().(*MeterSnapshot), + } +} + +// StdDev returns the standard deviation of the values in the sample. +func (t *StandardTimer) StdDev() float64 { + return t.histogram.StdDev() +} + +// Sum returns the sum in the sample. +func (t *StandardTimer) Sum() int64 { + return t.histogram.Sum() +} + +// Record the duration of the execution of the given function. +func (t *StandardTimer) Time(f func()) { + ts := time.Now() + f() + t.Update(time.Since(ts)) +} + +// Record the duration of an event. +func (t *StandardTimer) Update(d time.Duration) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(d)) + t.meter.Mark(1) +} + +// Record the duration of an event that started at a time and ends now. +func (t *StandardTimer) UpdateSince(ts time.Time) { + t.mutex.Lock() + defer t.mutex.Unlock() + t.histogram.Update(int64(time.Since(ts))) + t.meter.Mark(1) +} + +// Variance returns the variance of the values in the sample. +func (t *StandardTimer) Variance() float64 { + return t.histogram.Variance() +} + +// TimerSnapshot is a read-only copy of another Timer. +type TimerSnapshot struct { + histogram *HistogramSnapshot + meter *MeterSnapshot +} + +// Count returns the number of events recorded at the time the snapshot was +// taken. +func (t *TimerSnapshot) Count() int64 { return t.histogram.Count() } + +// Max returns the maximum value at the time the snapshot was taken. +func (t *TimerSnapshot) Max() int64 { return t.histogram.Max() } + +// Mean returns the mean value at the time the snapshot was taken. +func (t *TimerSnapshot) Mean() float64 { return t.histogram.Mean() } + +// Min returns the minimum value at the time the snapshot was taken. +func (t *TimerSnapshot) Min() int64 { return t.histogram.Min() } + +// Percentile returns an arbitrary percentile of sampled values at the time the +// snapshot was taken. +func (t *TimerSnapshot) Percentile(p float64) float64 { + return t.histogram.Percentile(p) +} + +// Percentiles returns a slice of arbitrary percentiles of sampled values at +// the time the snapshot was taken. +func (t *TimerSnapshot) Percentiles(ps []float64) []float64 { + return t.histogram.Percentiles(ps) +} + +// Rate1 returns the one-minute moving average rate of events per second at the +// time the snapshot was taken. +func (t *TimerSnapshot) Rate1() float64 { return t.meter.Rate1() } + +// Rate5 returns the five-minute moving average rate of events per second at +// the time the snapshot was taken. +func (t *TimerSnapshot) Rate5() float64 { return t.meter.Rate5() } + +// Rate15 returns the fifteen-minute moving average rate of events per second +// at the time the snapshot was taken. +func (t *TimerSnapshot) Rate15() float64 { return t.meter.Rate15() } + +// RateMean returns the meter's mean rate of events per second at the time the +// snapshot was taken. +func (t *TimerSnapshot) RateMean() float64 { return t.meter.RateMean() } + +// Snapshot returns the snapshot. +func (t *TimerSnapshot) Snapshot() Timer { return t } + +// StdDev returns the standard deviation of the values at the time the snapshot +// was taken. +func (t *TimerSnapshot) StdDev() float64 { return t.histogram.StdDev() } + +// Sum returns the sum at the time the snapshot was taken. +func (t *TimerSnapshot) Sum() int64 { return t.histogram.Sum() } + +// Time panics. +func (*TimerSnapshot) Time(func()) { + panic("Time called on a TimerSnapshot") +} + +// Update panics. +func (*TimerSnapshot) Update(time.Duration) { + panic("Update called on a TimerSnapshot") +} + +// UpdateSince panics. +func (*TimerSnapshot) UpdateSince(time.Time) { + panic("UpdateSince called on a TimerSnapshot") +} + +// Variance returns the variance of the values at the time the snapshot was +// taken. +func (t *TimerSnapshot) Variance() float64 { return t.histogram.Variance() } diff --git a/vendor/github.com/rcrowley/go-metrics/validate.sh b/vendor/github.com/rcrowley/go-metrics/validate.sh new file mode 100755 index 00000000..f6499982 --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/validate.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +# check there are no formatting issues +GOFMT_LINES=`gofmt -l . | wc -l | xargs` +test $GOFMT_LINES -eq 0 || echo "gofmt needs to be run, ${GOFMT_LINES} files have issues" + +# run the tests for the root package +go test . diff --git a/vendor/github.com/rcrowley/go-metrics/writer.go b/vendor/github.com/rcrowley/go-metrics/writer.go new file mode 100644 index 00000000..091e971d --- /dev/null +++ b/vendor/github.com/rcrowley/go-metrics/writer.go @@ -0,0 +1,100 @@ +package metrics + +import ( + "fmt" + "io" + "sort" + "time" +) + +// Write sorts writes each metric in the given registry periodically to the +// given io.Writer. +func Write(r Registry, d time.Duration, w io.Writer) { + for _ = range time.Tick(d) { + WriteOnce(r, w) + } +} + +// WriteOnce sorts and writes metrics in the given registry to the given +// io.Writer. +func WriteOnce(r Registry, w io.Writer) { + var namedMetrics namedMetricSlice + r.Each(func(name string, i interface{}) { + namedMetrics = append(namedMetrics, namedMetric{name, i}) + }) + + sort.Sort(namedMetrics) + for _, namedMetric := range namedMetrics { + switch metric := namedMetric.m.(type) { + case Counter: + fmt.Fprintf(w, "counter %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", metric.Count()) + case Gauge: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %9d\n", metric.Value()) + case GaugeFloat64: + fmt.Fprintf(w, "gauge %s\n", namedMetric.name) + fmt.Fprintf(w, " value: %f\n", metric.Value()) + case Healthcheck: + metric.Check() + fmt.Fprintf(w, "healthcheck %s\n", namedMetric.name) + fmt.Fprintf(w, " error: %v\n", metric.Error()) + case Histogram: + h := metric.Snapshot() + ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "histogram %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", h.Count()) + fmt.Fprintf(w, " min: %9d\n", h.Min()) + fmt.Fprintf(w, " max: %9d\n", h.Max()) + fmt.Fprintf(w, " mean: %12.2f\n", h.Mean()) + fmt.Fprintf(w, " stddev: %12.2f\n", h.StdDev()) + fmt.Fprintf(w, " median: %12.2f\n", ps[0]) + fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1]) + fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2]) + fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3]) + fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4]) + case Meter: + m := metric.Snapshot() + fmt.Fprintf(w, "meter %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", m.Count()) + fmt.Fprintf(w, " 1-min rate: %12.2f\n", m.Rate1()) + fmt.Fprintf(w, " 5-min rate: %12.2f\n", m.Rate5()) + fmt.Fprintf(w, " 15-min rate: %12.2f\n", m.Rate15()) + fmt.Fprintf(w, " mean rate: %12.2f\n", m.RateMean()) + case Timer: + t := metric.Snapshot() + ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999}) + fmt.Fprintf(w, "timer %s\n", namedMetric.name) + fmt.Fprintf(w, " count: %9d\n", t.Count()) + fmt.Fprintf(w, " min: %9d\n", t.Min()) + fmt.Fprintf(w, " max: %9d\n", t.Max()) + fmt.Fprintf(w, " mean: %12.2f\n", t.Mean()) + fmt.Fprintf(w, " stddev: %12.2f\n", t.StdDev()) + fmt.Fprintf(w, " median: %12.2f\n", ps[0]) + fmt.Fprintf(w, " 75%%: %12.2f\n", ps[1]) + fmt.Fprintf(w, " 95%%: %12.2f\n", ps[2]) + fmt.Fprintf(w, " 99%%: %12.2f\n", ps[3]) + fmt.Fprintf(w, " 99.9%%: %12.2f\n", ps[4]) + fmt.Fprintf(w, " 1-min rate: %12.2f\n", t.Rate1()) + fmt.Fprintf(w, " 5-min rate: %12.2f\n", t.Rate5()) + fmt.Fprintf(w, " 15-min rate: %12.2f\n", t.Rate15()) + fmt.Fprintf(w, " mean rate: %12.2f\n", t.RateMean()) + } + } +} + +type namedMetric struct { + name string + m interface{} +} + +// namedMetricSlice is a slice of namedMetrics that implements sort.Interface. +type namedMetricSlice []namedMetric + +func (nms namedMetricSlice) Len() int { return len(nms) } + +func (nms namedMetricSlice) Swap(i, j int) { nms[i], nms[j] = nms[j], nms[i] } + +func (nms namedMetricSlice) Less(i, j int) bool { + return nms[i].name < nms[j].name +} diff --git a/vendor/gopkg.in/karalabe/cookiejar.v2/LICENSE b/vendor/gopkg.in/karalabe/cookiejar.v2/LICENSE new file mode 100755 index 00000000..467d6087 --- /dev/null +++ b/vendor/gopkg.in/karalabe/cookiejar.v2/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2014 Péter Szilágyi. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Alternatively, the CookieJar toolbox may be used in accordance with the terms +and conditions contained in a signed written agreement between you and the +author(s). diff --git a/vendor/gopkg.in/karalabe/cookiejar.v2/collections/prque/prque.go b/vendor/gopkg.in/karalabe/cookiejar.v2/collections/prque/prque.go new file mode 100755 index 00000000..5c1967c6 --- /dev/null +++ b/vendor/gopkg.in/karalabe/cookiejar.v2/collections/prque/prque.go @@ -0,0 +1,66 @@ +// CookieJar - A contestant's algorithm toolbox +// Copyright (c) 2013 Peter Szilagyi. All rights reserved. +// +// CookieJar is dual licensed: use of this source code is governed by a BSD +// license that can be found in the LICENSE file. Alternatively, the CookieJar +// toolbox may be used in accordance with the terms and conditions contained +// in a signed written agreement between you and the author(s). + +// Package prque implements a priority queue data structure supporting arbitrary +// value types and float priorities. +// +// The reasoning behind using floats for the priorities vs. ints or interfaces +// was larger flexibility without sacrificing too much performance or code +// complexity. +// +// If you would like to use a min-priority queue, simply negate the priorities. +// +// Internally the queue is based on the standard heap package working on a +// sortable version of the block based stack. +package prque + +import ( + "container/heap" +) + +// Priority queue data structure. +type Prque struct { + cont *sstack +} + +// Creates a new priority queue. +func New() *Prque { + return &Prque{newSstack()} +} + +// Pushes a value with a given priority into the queue, expanding if necessary. +func (p *Prque) Push(data interface{}, priority float32) { + heap.Push(p.cont, &item{data, priority}) +} + +// Pops the value with the greates priority off the stack and returns it. +// Currently no shrinking is done. +func (p *Prque) Pop() (interface{}, float32) { + item := heap.Pop(p.cont).(*item) + return item.value, item.priority +} + +// Pops only the item from the queue, dropping the associated priority value. +func (p *Prque) PopItem() interface{} { + return heap.Pop(p.cont).(*item).value +} + +// Checks whether the priority queue is empty. +func (p *Prque) Empty() bool { + return p.cont.Len() == 0 +} + +// Returns the number of element in the priority queue. +func (p *Prque) Size() int { + return p.cont.Len() +} + +// Clears the contents of the priority queue. +func (p *Prque) Reset() { + *p = *New() +} diff --git a/vendor/gopkg.in/karalabe/cookiejar.v2/collections/prque/sstack.go b/vendor/gopkg.in/karalabe/cookiejar.v2/collections/prque/sstack.go new file mode 100755 index 00000000..9f393196 --- /dev/null +++ b/vendor/gopkg.in/karalabe/cookiejar.v2/collections/prque/sstack.go @@ -0,0 +1,91 @@ +// CookieJar - A contestant's algorithm toolbox +// Copyright (c) 2013 Peter Szilagyi. All rights reserved. +// +// CookieJar is dual licensed: use of this source code is governed by a BSD +// license that can be found in the LICENSE file. Alternatively, the CookieJar +// toolbox may be used in accordance with the terms and conditions contained +// in a signed written agreement between you and the author(s). + +package prque + +// The size of a block of data +const blockSize = 4096 + +// A prioritized item in the sorted stack. +type item struct { + value interface{} + priority float32 +} + +// Internal sortable stack data structure. Implements the Push and Pop ops for +// the stack (heap) functionality and the Len, Less and Swap methods for the +// sortability requirements of the heaps. +type sstack struct { + size int + capacity int + offset int + + blocks [][]*item + active []*item +} + +// Creates a new, empty stack. +func newSstack() *sstack { + result := new(sstack) + result.active = make([]*item, blockSize) + result.blocks = [][]*item{result.active} + result.capacity = blockSize + return result +} + +// Pushes a value onto the stack, expanding it if necessary. Required by +// heap.Interface. +func (s *sstack) Push(data interface{}) { + if s.size == s.capacity { + s.active = make([]*item, blockSize) + s.blocks = append(s.blocks, s.active) + s.capacity += blockSize + s.offset = 0 + } else if s.offset == blockSize { + s.active = s.blocks[s.size/blockSize] + s.offset = 0 + } + s.active[s.offset] = data.(*item) + s.offset++ + s.size++ +} + +// Pops a value off the stack and returns it. Currently no shrinking is done. +// Required by heap.Interface. +func (s *sstack) Pop() (res interface{}) { + s.size-- + s.offset-- + if s.offset < 0 { + s.offset = blockSize - 1 + s.active = s.blocks[s.size/blockSize] + } + res, s.active[s.offset] = s.active[s.offset], nil + return +} + +// Returns the length of the stack. Required by sort.Interface. +func (s *sstack) Len() int { + return s.size +} + +// Compares the priority of two elements of the stack (higher is first). +// Required by sort.Interface. +func (s *sstack) Less(i, j int) bool { + return s.blocks[i/blockSize][i%blockSize].priority > s.blocks[j/blockSize][j%blockSize].priority +} + +// Swaps two elements in the stack. Required by sort.Interface. +func (s *sstack) Swap(i, j int) { + ib, io, jb, jo := i/blockSize, i%blockSize, j/blockSize, j%blockSize + s.blocks[ib][io], s.blocks[jb][jo] = s.blocks[jb][jo], s.blocks[ib][io] +} + +// Resets the stack, effectively clearing its contents. +func (s *sstack) Reset() { + *s = *newSstack() +} diff --git a/vendor/vendor.json b/vendor/vendor.json new file mode 100644 index 00000000..23b59073 --- /dev/null +++ b/vendor/vendor.json @@ -0,0 +1,303 @@ +{ + "comment": "", + "ignore": "test", + "package": [ + { + "checksumSHA1": "W5qMYydPUfwKPyvbgSfF7YSAx6w=", + "path": "github.com/btcsuite/btcd/btcec", + "revision": "1bdb71328511a5225d6300c3c08a79172f667996", + "revisionTime": "2016-07-09T19:04:59Z" + }, + { + "checksumSHA1": "/Y/IvLkd3hSX1h3PDMHkkCBwK+4=", + "path": "github.com/ethereum/go-ethereum/common", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "NIN7nslnw4fUJlVcuxf5anvxAKQ=", + "path": "github.com/ethereum/go-ethereum/common/hexutil", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "Hd1Y5DkzYULQzJlSgYv2w5SiEAo=", + "path": "github.com/ethereum/go-ethereum/common/math", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "rofYNlEqnMen5Lg1N2+VcihuaIU=", + "path": "github.com/ethereum/go-ethereum/crypto", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "VsqOiLFDRSDa67wPeqlxKJmE0XE=", + "path": "github.com/ethereum/go-ethereum/crypto/secp256k1", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "yunX3AjO6JiMz0NSY/krvG3VWsk=", + "path": "github.com/ethereum/go-ethereum/crypto/sha3", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "CXoPEShhsjec6AmfyC6h5Ym8j18=", + "path": "github.com/ethereum/go-ethereum/ethdb", + "revision": "693d9ccbfbbcf7c32d3ff9fd8a432941e129a4ac", + "revisionTime": "2017-06-20T16:26:09Z" + }, + { + "checksumSHA1": "O56Cc6a0S2pK0oO9wZYO71xXeRM=", + "path": "github.com/ethereum/go-ethereum/event", + "revision": "693d9ccbfbbcf7c32d3ff9fd8a432941e129a4ac", + "revisionTime": "2017-06-20T16:26:09Z" + }, + { + "checksumSHA1": "NbRntdNRuwam0wGGNJ6HrR83P0M=", + "path": "github.com/ethereum/go-ethereum/log", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "LnUcnRFuZD3J8fsevk5kAJ+DlmU=", + "path": "github.com/ethereum/go-ethereum/metrics", + "revision": "693d9ccbfbbcf7c32d3ff9fd8a432941e129a4ac", + "revisionTime": "2017-06-20T16:26:09Z" + }, + { + "checksumSHA1": "dsD/vq8IdIgaiJJTfRnwKjF35oE=", + "path": "github.com/ethereum/go-ethereum/params", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "QARWkeJSFKOQF+/ryq6vqNmN8Q8=", + "path": "github.com/ethereum/go-ethereum/rlp", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "320PHjE15MUavTek9x6qojwQf7s=", + "path": "github.com/ethereum/go-ethereum/rpc", + "revision": "693d9ccbfbbcf7c32d3ff9fd8a432941e129a4ac", + "revisionTime": "2017-06-20T16:26:09Z" + }, + { + "checksumSHA1": "FdPv4Z5zhexDUEQDUDAnCQIKXnI=", + "path": "github.com/ethereum/go-ethereum/trie", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "tZVtZ5Zm7Q9AtARo7xfYh28ELXI=", + "path": "github.com/getamis/go-ethereum/common", + "revision": "57750cbf051bb25fce769f3f4869eb216672f22f", + "revisionTime": "2017-06-19T05:54:01Z", + "version": "=feature/pbft", + "versionExact": "feature/pbft" + }, + { + "checksumSHA1": "YvypTMzv0Ec9C9iwOCIRbBcl9XY=", + "path": "github.com/getamis/go-ethereum/common/hexutil", + "revision": "57750cbf051bb25fce769f3f4869eb216672f22f", + "revisionTime": "2017-06-19T05:54:01Z", + "version": "=feature/pbft", + "versionExact": "feature/pbft" + }, + { + "checksumSHA1": "kSu3LWnvEXHTgSH9KB3Q/eGAHAk=", + "path": "github.com/getamis/go-ethereum/core", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "xCsTCsFLsh4eJhcOXQfaIWQxtKo=", + "path": "github.com/getamis/go-ethereum/core/types", + "revision": "57750cbf051bb25fce769f3f4869eb216672f22f", + "revisionTime": "2017-06-19T05:54:01Z", + "version": "=feature/pbft", + "versionExact": "feature/pbft" + }, + { + "checksumSHA1": "ovKUpgF7FRdoZ+7ojAtKlUcBn/Q=", + "path": "github.com/getamis/go-ethereum/params", + "revision": "431cf2a1e453346bcc627ac1fb9df3950a6c3499", + "revisionTime": "2017-06-16T14:11:54Z" + }, + { + "checksumSHA1": "602c64HqPYM1v7dRjkFHEKxYinM=", + "path": "github.com/getamis/go-ethereum/rlp", + "revision": "57750cbf051bb25fce769f3f4869eb216672f22f", + "revisionTime": "2017-06-19T05:54:01Z", + "version": "=feature/pbft", + "versionExact": "feature/pbft" + }, + { + "checksumSHA1": "VcLNrvCcnZuSnebTxMRyNtzY3ZY=", + "path": "github.com/go-stack/stack", + "revision": "7a2f19628aabfe68f0766b59e74d6315f8347d22", + "revisionTime": "2017-05-04T03:43:18Z" + }, + { + "checksumSHA1": "p/8vSviYF91gFflhrt5vkyksroo=", + "path": "github.com/golang/snappy", + "revision": "553a641470496b2327abcac10b36396bd98e45c9", + "revisionTime": "2017-02-15T23:32:05Z" + }, + { + "checksumSHA1": "d9PxF1XQGLMJZRct2R8qVM/eYlE=", + "path": "github.com/hashicorp/golang-lru", + "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6", + "revisionTime": "2016-08-13T22:13:03Z" + }, + { + "checksumSHA1": "9hffs0bAIU6CquiRhKQdzjHnKt0=", + "path": "github.com/hashicorp/golang-lru/simplelru", + "revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6", + "revisionTime": "2016-08-13T22:13:03Z" + }, + { + "checksumSHA1": "A6nZdZ1/lTOVINhIndyw2ZWN9JU=", + "path": "github.com/naoina/go-stringutil", + "revision": "6b638e95a32d0c1131db0e7fe83775cbea4a0d0b", + "revisionTime": "2015-11-18T23:44:43Z" + }, + { + "checksumSHA1": "2w8GeWfyeUrrVyj5MitxcHhaO7s=", + "path": "github.com/naoina/toml", + "revision": "e6f5723bf2a66af014955e0888881314cf294129", + "revisionTime": "2017-04-28T05:41:52Z" + }, + { + "checksumSHA1": "xZBlSMT5o/A+EDOro6KbfHZwSNc=", + "path": "github.com/naoina/toml/ast", + "revision": "e6f5723bf2a66af014955e0888881314cf294129", + "revisionTime": "2017-04-28T05:41:52Z" + }, + { + "checksumSHA1": "KAzbLjI9MzW2tjfcAsK75lVRp6I=", + "path": "github.com/rcrowley/go-metrics", + "revision": "1f30fe9094a513ce4c700b9a54458bbb0c96996c", + "revisionTime": "2016-11-28T21:05:44Z" + }, + { + "checksumSHA1": "q/d9nXRQYKEJ/EWn+5y6jL8rPGs=", + "path": "github.com/rcrowley/go-metrics/exp", + "revision": "1f30fe9094a513ce4c700b9a54458bbb0c96996c", + "revisionTime": "2016-11-28T21:05:44Z" + }, + { + "checksumSHA1": "lZmPAbekxLbMFQirB/vzbdI+5O8=", + "path": "github.com/rs/cors", + "revision": "8dd4211afb5d08dbb39a533b9bb9e4b486351df6", + "revisionTime": "2017-06-08T16:51:55Z" + }, + { + "checksumSHA1": "HcDa/j4eMiKGYEo8qmrW+2NDFcE=", + "path": "github.com/syndtr/goleveldb/leveldb", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "EKIow7XkgNdWvR/982ffIZxKG8Y=", + "path": "github.com/syndtr/goleveldb/leveldb/cache", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "5KPgnvCPlR0ysDAqo6jApzRQ3tw=", + "path": "github.com/syndtr/goleveldb/leveldb/comparer", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "1DRAxdlWzS4U0xKN/yQ/fdNN7f0=", + "path": "github.com/syndtr/goleveldb/leveldb/errors", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "eqKeD6DS7eNCtxVYZEHHRKkyZrw=", + "path": "github.com/syndtr/goleveldb/leveldb/filter", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "8dXuAVIsbtaMiGGuHjzGR6Ny/5c=", + "path": "github.com/syndtr/goleveldb/leveldb/iterator", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "gJY7bRpELtO0PJpZXgPQ2BYFJ88=", + "path": "github.com/syndtr/goleveldb/leveldb/journal", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "j+uaQ6DwJ50dkIdfMQu1TXdlQcY=", + "path": "github.com/syndtr/goleveldb/leveldb/memdb", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "UmQeotV+m8/FduKEfLOhjdp18rs=", + "path": "github.com/syndtr/goleveldb/leveldb/opt", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "tQ2AqXXAEy9icbZI9dLVdZGvWMw=", + "path": "github.com/syndtr/goleveldb/leveldb/storage", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "gWFPMz8OQeul0t54RM66yMTX49g=", + "path": "github.com/syndtr/goleveldb/leveldb/table", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "4zil8Gwg8VPkDn1YzlgCvtukJFU=", + "path": "github.com/syndtr/goleveldb/leveldb/util", + "revision": "8c81ea47d4c41a385645e133e15510fc6a2a74b4", + "revisionTime": "2017-04-09T01:48:31Z" + }, + { + "checksumSHA1": "y/oIaxq2d3WPizRZfVjo8RCRYTU=", + "path": "golang.org/x/crypto/ripemd160", + "revision": "adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d", + "revisionTime": "2017-06-19T06:03:41Z" + }, + { + "checksumSHA1": "7EZyXN0EmZLgGxZxK01IJua4c8o=", + "path": "golang.org/x/net/websocket", + "revision": "fe686d45ea04bc1bd4eff6a52865ce8757320325", + "revisionTime": "2017-06-18T05:18:41Z" + }, + { + "checksumSHA1": "NGg7/qIJVUfXi7xnEyyDLocdi6Y=", + "path": "gopkg.in/fatih/set.v0", + "revision": "27c40922c40b43fe04554d8223a402af3ea333f3", + "revisionTime": "2014-12-10T08:48:24Z" + }, + { + "checksumSHA1": "DQXNV0EivoHm4q+bkdahYXrjjfE=", + "path": "gopkg.in/karalabe/cookiejar.v2/collections/prque", + "revision": "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57", + "revisionTime": "2015-07-24T13:16:13Z" + }, + { + "checksumSHA1": "0xgs8lwcWLUffemlj+SsgKlxvDU=", + "path": "gopkg.in/natefinch/npipe.v2", + "revision": "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6", + "revisionTime": "2016-06-21T03:49:01Z" + } + ], + "rootPath": "github.com/Istanbul-tools" +}