Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/btcsuite/btcd
Browse files Browse the repository at this point in the history
  • Loading branch information
losh11 committed Jan 27, 2020
2 parents 92166e4 + f3ec130 commit cb9307d
Show file tree
Hide file tree
Showing 33 changed files with 1,317 additions and 373 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ cache:
- $GOPATH/github.com/golang
- $GOPATH/gopkg.in/alecthomas
go:
- "1.11.x"
- "1.13.x"
sudo: false
install:
- export PATH=$PATH:$PWD/linux-amd64/
Expand Down
54 changes: 20 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,38 @@
ltcd
====
# ltcd

[![Build Status](https://travis-ci.org/ltcsuite/ltcd.png?branch=master)](https://travis-ci.org/ltcsuite/ltcd)

ltcd is an alternative full node bitcoin implementation written in Go (golang).

This project is currently under active development and is in a Beta state. It
This project is currently under active development and is in a Beta state. It
is extremely stable and has been in production use since October 2013.

It properly downloads, validates, and serves the block chain using the exact
rules (including consensus bugs) for block acceptance as Bitcoin Core. We have
taken great care to avoid ltcd causing a fork to the block chain. It includes a
rules (including consensus bugs) for block acceptance as Bitcoin Core. We have
taken great care to avoid ltcd causing a fork to the block chain. It includes a
full block validation testing framework which contains all of the 'official'
block acceptance tests (and some additional ones) that is run on every pull
request to help ensure it properly follows consensus. Also, it passes all of
request to help ensure it properly follows consensus. Also, it passes all of
the JSON test data in the Bitcoin Core code.

It also properly relays newly mined blocks, maintains a transaction pool, and
relays individual transactions that have not yet made it into a block. It
relays individual transactions that have not yet made it into a block. It
ensures all individual transactions admitted to the pool follow the rules
required by the block chain and also includes more strict checks which filter
transactions based on miner requirements ("standard" transactions).

One key difference between ltcd and Bitcoin Core is that ltcd does *NOT* include
wallet functionality and this was a very intentional design decision. See the
One key difference between ltcd and Bitcoin Core is that ltcd does _NOT_ include
wallet functionality and this was a very intentional design decision. See the
blog entry [here](https://blog.conformal.com/ltcd-not-your-moms-bitcoin-daemon)
for more details. This means you can't actually make or receive payments
directly with ltcd. That functionality is provided by the
for more details. This means you can't actually make or receive payments
directly with ltcd. That functionality is provided by the
[btcwallet](https://github.com/btcsuite/btcwallet) and
[Paymetheus](https://github.com/btcsuite/Paymetheus) (Windows-only) projects
which are both under active development.

## Requirements

[Go](http://golang.org) 1.11 or newer.
[Go](http://golang.org) 1.12 or newer.

## Installation

Expand All @@ -53,9 +52,9 @@ $ go version
$ go env GOROOT GOPATH
```

NOTE: The `GOROOT` and `GOPATH` above must not be the same path. It is
NOTE: The `GOROOT` and `GOPATH` above must not be the same path. It is
recommended that `GOPATH` is set to a directory in your home directory such as
`~/goprojects` to avoid write permission issues. It is also recommended to add
`~/goprojects` to avoid write permission issues. It is also recommended to add
`$GOPATH/bin` to your `PATH` at this point.

- Run the following commands to obtain ltcd, all dependencies, and install it:
Expand All @@ -65,7 +64,7 @@ $ cd $GOPATH/src/github.com/ltcsuite/ltcd
$ GO111MODULE=on go install -v . ./cmd/...
```

- ltcd (and utilities) will now be installed in ```$GOPATH/bin```. If you did
- ltcd (and utilities) will now be installed in `$GOPATH/bin`. If you did
not already add the bin directory to your system path during Go installation,
we recommend you do so now.

Expand Down Expand Up @@ -114,27 +113,14 @@ is used for this project.

## Documentation

The documentation is a work-in-progress. It is located in the [docs](https://github.com/ltcsuite/ltcd/tree/master/docs) folder.
The documentation is a work-in-progress. It is located in the [docs](https://github.com/ltcsuite/ltcd/tree/master/docs) folder.

## GPG Verification Key
## Release Verification

All official release tags are signed by Conformal so users can ensure the code
has not been tampered with and is coming from the ltcsuite developers. To
verify the signature perform the following:

- Download the Conformal public key:
https://raw.githubusercontent.com/ltcsuite/ltcd/master/release/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
```
Please see our [documentation on the current build/verification
process](https://github.com/ltcsuite/ltcd/tree/master/release) for all our
releases for information on how to verify the integrity of published releases
using our reproducible build system.

## License

Expand Down
24 changes: 23 additions & 1 deletion btcec/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

package btcec

import "testing"
import (
"encoding/hex"
"testing"
)

// BenchmarkAddJacobian benchmarks the secp256k1 curve addJacobian function with
// Z values of 1 so that the associated optimizations are used.
Expand Down Expand Up @@ -121,3 +124,22 @@ func BenchmarkFieldNormalize(b *testing.B) {
f.Normalize()
}
}

// BenchmarkParseCompressedPubKey benchmarks how long it takes to decompress and
// validate a compressed public key from a byte array.
func BenchmarkParseCompressedPubKey(b *testing.B) {
rawPk, _ := hex.DecodeString("0234f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6")

var (
pk *PublicKey
err error
)

b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
pk, err = ParsePubKey(rawPk, S256())
}
_ = pk
_ = err
}
24 changes: 21 additions & 3 deletions btcec/btcec.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,17 @@ var (
// interface from crypto/elliptic.
type KoblitzCurve struct {
*elliptic.CurveParams
q *big.Int

// q is the value (P+1)/4 used to compute the square root of field
// elements.
q *big.Int

H int // cofactor of the curve.
halfOrder *big.Int // half the order N

// fieldB is the constant B of the curve as a fieldVal.
fieldB *fieldVal

// byteSize is simply the bit size / 8 and is provided for convenience
// since it is calculated repeatedly.
byteSize int
Expand Down Expand Up @@ -879,12 +886,22 @@ func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
return curve.fieldJacobianToBigAffine(qx, qy, qz)
}

// QPlus1Div4 returns the Q+1/4 constant for the curve for use in calculating
// square roots via exponention.
// QPlus1Div4 returns the (P+1)/4 constant for the curve for use in calculating
// square roots via exponentiation.
//
// DEPRECATED: The actual value returned is (P+1)/4, where as the original
// method name implies that this value is (((P+1)/4)+1)/4. This method is kept
// to maintain backwards compatibility of the API. Use Q() instead.
func (curve *KoblitzCurve) QPlus1Div4() *big.Int {
return curve.q
}

// Q returns the (P+1)/4 constant for the curve for use in calculating square
// roots via exponentiation.
func (curve *KoblitzCurve) Q() *big.Int {
return curve.q
}

var initonce sync.Once
var secp256k1 KoblitzCurve

Expand Down Expand Up @@ -917,6 +934,7 @@ func initS256() {
big.NewInt(1)), big.NewInt(4))
secp256k1.H = 1
secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1)
secp256k1.fieldB = new(fieldVal).SetByteSlice(secp256k1.B.Bytes())

// Provided for convenience since this gets computed repeatedly.
secp256k1.byteSize = secp256k1.BitSize / 8
Expand Down
129 changes: 129 additions & 0 deletions btcec/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,20 @@ const (
fieldPrimeWordOne = 0x3ffffbf
)

var (
// fieldQBytes is the value Q = (P+1)/4 for the secp256k1 prime P. This
// value is used to efficiently compute the square root of values in the
// field via exponentiation. The value of Q in hex is:
//
// Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c
fieldQBytes = []byte{
0x3f, 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, 0xbf, 0xff, 0xff, 0x0c,
}
)

// fieldVal implements optimized fixed-precision arithmetic over the
// secp256k1 finite field. This means all arithmetic is performed modulo
// 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f. It
Expand Down Expand Up @@ -1221,3 +1235,118 @@ func (f *fieldVal) Inverse() *fieldVal {
f.Square().Square().Square().Square().Square() // f = a^(2^256 - 4294968320)
return f.Mul(&a45) // f = a^(2^256 - 4294968275) = a^(p-2)
}

// SqrtVal computes the square root of x modulo the curve's prime, and stores
// the result in f. The square root is computed via exponentiation of x by the
// value Q = (P+1)/4 using the curve's precomputed big-endian representation of
// the Q. This method uses a modified version of square-and-multiply
// exponentiation over secp256k1 fieldVals to operate on bytes instead of bits,
// which offers better performance over both big.Int exponentiation and bit-wise
// square-and-multiply.
//
// NOTE: This method only works when P is intended to be the secp256k1 prime and
// is not constant time. The returned value is of magnitude 1, but is
// denormalized.
func (f *fieldVal) SqrtVal(x *fieldVal) *fieldVal {
// The following computation iteratively computes x^((P+1)/4) = x^Q
// using the recursive, piece-wise definition:
//
// x^n = (x^2)^(n/2) mod P if n is even
// x^n = x(x^2)^(n-1/2) mod P if n is odd
//
// Given n in its big-endian representation b_k, ..., b_0, x^n can be
// computed by defining the sequence r_k+1, ..., r_0, where:
//
// r_k+1 = 1
// r_i = (r_i+1)^2 * x^b_i for i = k, ..., 0
//
// The final value r_0 = x^n.
//
// See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more
// details.
//
// This can be further optimized, by observing that the value of Q in
// secp256k1 has the value:
//
// Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c
//
// We can unroll the typical bit-wise interpretation of the
// exponentiation algorithm above to instead operate on bytes.
// This reduces the number of comparisons by an order of magnitude,
// reducing the overhead of failed branch predictions and additional
// comparisons in this method.
//
// Since there there are only 4 unique bytes of Q, this keeps the jump
// table small without the need to handle all possible 8-bit values.
// Further, we observe that 29 of the 32 bytes are 0xff; making the
// first case handle 0xff therefore optimizes the hot path.
f.SetInt(1)
for _, b := range fieldQBytes {
switch b {

// Most common case, where all 8 bits are set.
case 0xff:
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)

// First byte of Q (0x3f), where all but the top two bits are
// set. Note that this case only applies six operations, since
// the highest bit of Q resides in bit six of the first byte. We
// ignore the first two bits, since squaring for these bits will
// result in an invalid result. We forgo squaring f before the
// first multiply, since 1^2 = 1.
case 0x3f:
f.Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)

// Byte 28 of Q (0xbf), where only bit 7 is unset.
case 0xbf:
f.Square().Mul(x)
f.Square()
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)
f.Square().Mul(x)

// Byte 31 of Q (0x0c), where only bits 3 and 4 are set.
default:
f.Square()
f.Square()
f.Square()
f.Square()
f.Square().Mul(x)
f.Square().Mul(x)
f.Square()
f.Square()
}
}

return f
}

// Sqrt computes the square root of f modulo the curve's prime, and stores the
// result in f. The square root is computed via exponentiation of x by the value
// Q = (P+1)/4 using the curve's precomputed big-endian representation of the Q.
// This method uses a modified version of square-and-multiply exponentiation
// over secp256k1 fieldVals to operate on bytes instead of bits, which offers
// better performance over both big.Int exponentiation and bit-wise
// square-and-multiply.
//
// NOTE: This method only works when P is intended to be the secp256k1 prime and
// is not constant time. The returned value is of magnitude 1, but is
// denormalized.
func (f *fieldVal) Sqrt() *fieldVal {
return f.SqrtVal(f)
}

0 comments on commit cb9307d

Please sign in to comment.