Merge pull request #315 from nspcc-dev/drop-redundant-dev-code-part-1

Drop redundant dev code part 1
This commit is contained in:
Roman Khimov 2019-08-26 13:45:35 +03:00 committed by GitHub
commit 0beb63fd47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 345 additions and 2181 deletions

View file

@ -1,93 +0,0 @@
package aes
import (
"crypto/aes"
"crypto/cipher"
)
// Encrypt encrypts the key with the given source.
func Encrypt(src, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
ecb := newECBEncrypter(block)
out := make([]byte, len(src))
ecb.CryptBlocks(out, src)
return out, nil
}
// Decrypt decrypts the encrypted source with the given key.
func Decrypt(crypted, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockMode := newECBDecrypter(block)
out := make([]byte, len(crypted))
blockMode.CryptBlocks(out, crypted)
return out, nil
}
type ecb struct {
b cipher.Block
blockSize int
}
func newECB(b cipher.Block) *ecb {
return &ecb{
b: b,
blockSize: b.BlockSize(),
}
}
type ecbEncrypter ecb
func newECBEncrypter(b cipher.Block) cipher.BlockMode {
return (*ecbEncrypter)(newECB(b))
}
func (ecb *ecbEncrypter) BlockSize() int {
return ecb.blockSize
}
func (ecb *ecbEncrypter) CryptBlocks(dst, src []byte) {
if len(src)%ecb.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
ecb.b.Encrypt(dst, src[:ecb.blockSize])
src = src[ecb.blockSize:]
dst = dst[ecb.blockSize:]
}
}
type ecbDecrypter ecb
func newECBDecrypter(b cipher.Block) cipher.BlockMode {
return (*ecbDecrypter)(newECB(b))
}
func (ecb ecbDecrypter) BlockSize() int {
return ecb.blockSize
}
func (ecb *ecbDecrypter) CryptBlocks(dst, src []byte) {
if len(src)%ecb.blockSize != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
ecb.b.Decrypt(dst, src[:ecb.blockSize])
src = src[ecb.blockSize:]
dst = dst[ecb.blockSize:]
}
}

View file

@ -1,126 +0,0 @@
package base58
import (
"bytes"
"fmt"
"math/big"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
)
const prefix rune = '1'
var decodeMap = map[rune]int64{
'1': 0, '2': 1, '3': 2, '4': 3, '5': 4,
'6': 5, '7': 6, '8': 7, '9': 8, 'A': 9,
'B': 10, 'C': 11, 'D': 12, 'E': 13, 'F': 14,
'G': 15, 'H': 16, 'J': 17, 'K': 18, 'L': 19,
'M': 20, 'N': 21, 'P': 22, 'Q': 23, 'R': 24,
'S': 25, 'T': 26, 'U': 27, 'V': 28, 'W': 29,
'X': 30, 'Y': 31, 'Z': 32, 'a': 33, 'b': 34,
'c': 35, 'd': 36, 'e': 37, 'f': 38, 'g': 39,
'h': 40, 'i': 41, 'j': 42, 'k': 43, 'm': 44,
'n': 45, 'o': 46, 'p': 47, 'q': 48, 'r': 49,
's': 50, 't': 51, 'u': 52, 'v': 53, 'w': 54,
'x': 55, 'y': 56, 'z': 57,
}
// Decode decodes the base58 encoded string.
func Decode(s string) ([]byte, error) {
var (
startIndex = 0
zero = 0
)
for i, c := range s {
if c == prefix {
zero++
} else {
startIndex = i
break
}
}
var (
n = big.NewInt(0)
div = big.NewInt(58)
)
for _, c := range s[startIndex:] {
charIndex, ok := decodeMap[c]
if !ok {
return nil, fmt.Errorf(
"invalid character '%c' when decoding this base58 string: '%s'", c, s,
)
}
n.Add(n.Mul(n, div), big.NewInt(charIndex))
}
out := n.Bytes()
buf := make([]byte, (zero + len(out)))
copy(buf[zero:], out[:])
return buf, nil
}
// Encode encodes a byte slice to be a base58 encoded string.
func Encode(bytes []byte) string {
var (
lookupTable = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
x = new(big.Int).SetBytes(bytes)
r = new(big.Int)
m = big.NewInt(58)
zero = big.NewInt(0)
encoded string
)
for x.Cmp(zero) > 0 {
x.QuoRem(x, m, r)
encoded = string(lookupTable[r.Int64()]) + encoded
}
return encoded
}
// CheckDecode decodes the given string.
func CheckDecode(s string) (b []byte, err error) {
b, err = Decode(s)
if err != nil {
return nil, err
}
for i := 0; i < len(s); i++ {
if s[i] != '1' {
break
}
b = append([]byte{0x00}, b...)
}
if len(b) < 5 {
return nil, fmt.Errorf("Invalid base-58 check string: missing checksum")
}
hash, err := hash.DoubleSha256(b[:len(b)-4])
if err != nil {
return nil, fmt.Errorf("Could not double sha256 data")
}
if bytes.Compare(hash[0:4], b[len(b)-4:]) != 0 {
return nil, fmt.Errorf("Invalid base-58 check string: invalid checksum")
}
// Strip the 4 byte long hash.
b = b[:len(b)-4]
return b, nil
}
// CheckEncode encodes b into a base-58 check encoded string.
func CheckEncode(b []byte) (string, error) {
hash, err := hash.DoubleSha256(b)
if err != nil {
return "", fmt.Errorf("Could not double sha256 data")
}
b = append(b, hash[0:4]...)
return Encode(b), nil
}

View file

@ -1,88 +0,0 @@
package hash
import (
"crypto/sha256"
"io"
"github.com/CityOfZion/neo-go/pkg/wire/util"
"golang.org/x/crypto/ripemd160"
)
// Sha256 hashes the incoming byte slice
// using the sha256 algorithm
func Sha256(data []byte) (util.Uint256, error) {
var hash util.Uint256
hasher := sha256.New()
hasher.Reset()
_, err := hasher.Write(data)
hash, err = util.Uint256DecodeBytes(hasher.Sum(nil))
if err != nil {
return hash, err
}
return hash, nil
}
// DoubleSha256 performs sha256 twice on the given data
func DoubleSha256(data []byte) (util.Uint256, error) {
var hash util.Uint256
h1, err := Sha256(data)
if err != nil {
return hash, err
}
hash, err = Sha256(h1.Bytes())
if err != nil {
return hash, err
}
return hash, nil
}
// RipeMD160 performs the RIPEMD160 hash algorithm
// on the given data
func RipeMD160(data []byte) (util.Uint160, error) {
var hash util.Uint160
hasher := ripemd160.New()
hasher.Reset()
_, err := io.WriteString(hasher, string(data))
hash, err = util.Uint160DecodeBytes(hasher.Sum(nil))
if err != nil {
return hash, err
}
return hash, nil
}
// Hash160 performs sha256 and then ripemd160
// on the given data
func Hash160(data []byte) (util.Uint160, error) {
var hash util.Uint160
h1, err := Sha256(data)
h2, err := RipeMD160(h1.Bytes())
hash, err = util.Uint160DecodeBytes(h2.Bytes())
if err != nil {
return hash, err
}
return hash, nil
}
// Checksum returns the checksum for a given piece of data
// using sha256 twice as the hash algorithm
func Checksum(data []byte) ([]byte, error) {
hash, err := Sum(data)
if err != nil {
return nil, err
}
return hash[:4], nil
}
// Sum performs sha256 twice on the given data
// XXX(issue): We should remove this and just do doublesha256
func Sum(b []byte) (util.Uint256, error) {
hash, err := DoubleSha256((b))
return hash, err
}

View file

@ -15,7 +15,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/crypto/base58" "github.com/CityOfZion/neo-go/pkg/crypto/base58"
"github.com/CityOfZion/neo-go/pkg/crypto/elliptic" "github.com/CityOfZion/neo-go/pkg/crypto/elliptic"
"github.com/CityOfZion/neo-go/pkg/crypto/hash" "github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/crypto/rfc6979" "github.com/anthdm/rfc6979"
) )
// PrivateKey represents a NEO private key. // PrivateKey represents a NEO private key.

View file

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Coda Hale
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.

View file

@ -1,45 +0,0 @@
package rfc6979
import (
"crypto/dsa"
"hash"
"math/big"
)
// SignDSA signs an arbitrary length hash (which should be the result of hashing
// a larger message) using the private key, priv. It returns the signature as a
// pair of integers.
//
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
func SignDSA(priv *dsa.PrivateKey, hash []byte, alg func() hash.Hash) (r, s *big.Int, err error) {
n := priv.Q.BitLen()
if n&7 != 0 {
err = dsa.ErrInvalidPublicKey
return
}
n >>= 3
generateSecret(priv.Q, priv.X, alg, hash, func(k *big.Int) bool {
inv := new(big.Int).ModInverse(k, priv.Q)
r = new(big.Int).Exp(priv.G, k, priv.P)
r.Mod(r, priv.Q)
if r.Sign() == 0 {
return false
}
z := new(big.Int).SetBytes(hash)
s = new(big.Int).Mul(priv.X, r)
s.Add(s, z)
s.Mod(s, priv.Q)
s.Mul(s, inv)
s.Mod(s, priv.Q)
return s.Sign() != 0
})
return
}

View file

@ -1,270 +0,0 @@
package rfc6979_test
import (
"crypto/dsa"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"hash"
"math/big"
"testing"
"github.com/o3labs/neo-utils/neoutils/rfc6979"
)
type dsaFixture struct {
name string
key *dsaKey
alg func() hash.Hash
message string
r, s string
}
type dsaKey struct {
key *dsa.PrivateKey
subgroup int
}
var dsa1024 = &dsaKey{
key: &dsa.PrivateKey{
PublicKey: dsa.PublicKey{
Parameters: dsa.Parameters{
P: dsaLoadInt("86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED8873ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779"),
Q: dsaLoadInt("996F967F6C8E388D9E28D01E205FBA957A5698B1"),
G: dsaLoadInt("07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA417BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD"),
},
Y: dsaLoadInt("5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F65392195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E682F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B"),
},
X: dsaLoadInt("411602CB19A6CCC34494D79D98EF1E7ED5AF25F7"),
},
subgroup: 160,
}
var dsa2048 = &dsaKey{
key: &dsa.PrivateKey{
PublicKey: dsa.PublicKey{
Parameters: dsa.Parameters{
P: dsaLoadInt("9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B"),
Q: dsaLoadInt("F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F"),
G: dsaLoadInt("5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7"),
},
Y: dsaLoadInt("667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF"),
},
X: dsaLoadInt("69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC"),
},
subgroup: 256,
}
var dsaFixtures = []dsaFixture{
// DSA, 1024 Bits
// https://tools.ietf.org/html/rfc6979#appendix-A.2.1
dsaFixture{
name: "1024/SHA-1 #1",
key: dsa1024,
alg: sha1.New,
message: "sample",
r: "2E1A0C2562B2912CAAF89186FB0F42001585DA55",
s: "29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5",
},
dsaFixture{
name: "1024/SHA-224 #1",
key: dsa1024,
alg: sha256.New224,
message: "sample",
r: "4BC3B686AEA70145856814A6F1BB53346F02101E",
s: "410697B92295D994D21EDD2F4ADA85566F6F94C1",
},
dsaFixture{
name: "1024/SHA-256 #1",
key: dsa1024,
alg: sha256.New,
message: "sample",
r: "81F2F5850BE5BC123C43F71A3033E9384611C545",
s: "4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89",
},
dsaFixture{
name: "1024/SHA-384 #1",
key: dsa1024,
alg: sha512.New384,
message: "sample",
r: "07F2108557EE0E3921BC1774F1CA9B410B4CE65A",
s: "54DF70456C86FAC10FAB47C1949AB83F2C6F7595",
},
dsaFixture{
name: "1024/SHA-512 #1",
key: dsa1024,
alg: sha512.New,
message: "sample",
r: "16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B",
s: "02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C",
},
dsaFixture{
name: "1024/SHA-1 #2",
key: dsa1024,
alg: sha1.New,
message: "test",
r: "42AB2052FD43E123F0607F115052A67DCD9C5C77",
s: "183916B0230D45B9931491D4C6B0BD2FB4AAF088",
},
dsaFixture{
name: "1024/SHA-224 #2",
key: dsa1024,
alg: sha256.New224,
message: "test",
r: "6868E9964E36C1689F6037F91F28D5F2C30610F2",
s: "49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F",
},
dsaFixture{
name: "1024/SHA-256 #2",
key: dsa1024,
alg: sha256.New,
message: "test",
r: "22518C127299B0F6FDC9872B282B9E70D0790812",
s: "6837EC18F150D55DE95B5E29BE7AF5D01E4FE160",
},
dsaFixture{
name: "1024/SHA-384 #2",
key: dsa1024,
alg: sha512.New384,
message: "test",
r: "854CF929B58D73C3CBFDC421E8D5430CD6DB5E66",
s: "91D0E0F53E22F898D158380676A871A157CDA622",
},
dsaFixture{
name: "1024/SHA-512 #2",
key: dsa1024,
alg: sha512.New,
message: "test",
r: "8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0",
s: "7C670C7AD72B6C050C109E1790008097125433E8",
},
// DSA, 2048 Bits
// https://tools.ietf.org/html/rfc6979#appendix-A.2.2
dsaFixture{
name: "2048/SHA-1 #1",
key: dsa2048,
alg: sha1.New,
message: "sample",
r: "3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A",
s: "D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF",
},
dsaFixture{
name: "2048/SHA-224 #1",
key: dsa2048,
alg: sha256.New224,
message: "sample",
r: "DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C",
s: "A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC",
},
dsaFixture{
name: "2048/SHA-256 #1",
key: dsa2048,
alg: sha256.New,
message: "sample",
r: "EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809",
s: "7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53",
},
dsaFixture{
name: "2048/SHA-384 #1",
key: dsa2048,
alg: sha512.New384,
message: "sample",
r: "B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B",
s: "19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B",
},
dsaFixture{
name: "2048/SHA-512 #1",
key: dsa2048,
alg: sha512.New,
message: "sample",
r: "2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E",
s: "D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351",
},
dsaFixture{
name: "2048/SHA-1 #2",
key: dsa2048,
alg: sha1.New,
message: "test",
r: "C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0",
s: "414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA",
},
dsaFixture{
name: "2048/SHA-224 #2",
key: dsa2048,
alg: sha256.New224,
message: "test",
r: "272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3",
s: "E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806",
},
dsaFixture{
name: "2048/SHA-256 #2",
key: dsa2048,
alg: sha256.New,
message: "test",
r: "8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0",
s: "7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E",
},
dsaFixture{
name: "2048/SHA-384 #2",
key: dsa2048,
alg: sha512.New384,
message: "test",
r: "239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE",
s: "6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961",
},
dsaFixture{
name: "2048/SHA-512 #2",
key: dsa2048,
alg: sha512.New,
message: "test",
r: "89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307",
s: "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1",
},
}
func TestDSASignatures(t *testing.T) {
for _, f := range dsaFixtures {
testDsaFixture(&f, t)
}
}
func testDsaFixture(f *dsaFixture, t *testing.T) {
t.Logf("Testing %s", f.name)
h := f.alg()
h.Write([]byte(f.message))
digest := h.Sum(nil)
g := f.key.subgroup / 8
if len(digest) > g {
digest = digest[0:g]
}
r, s, err := rfc6979.SignDSA(f.key.key, digest, f.alg)
if err != nil {
t.Error(err)
return
}
expectedR := dsaLoadInt(f.r)
expectedS := dsaLoadInt(f.s)
if r.Cmp(expectedR) != 0 {
t.Errorf("%s: Expected R of %X, got %X", f.name, expectedR, r)
}
if s.Cmp(expectedS) != 0 {
t.Errorf("%s: Expected S of %X, got %X", f.name, expectedS, s)
}
}
func dsaLoadInt(s string) *big.Int {
b, err := hex.DecodeString(s)
if err != nil {
panic(err)
}
return new(big.Int).SetBytes(b)
}

View file

@ -1,59 +0,0 @@
package rfc6979
import (
"hash"
"math/big"
"github.com/CityOfZion/neo-go/pkg/crypto/elliptic"
)
// SignECDSA signs an arbitrary length hash (which should be the result of
// hashing a larger message) using the private key, priv. It returns the
// signature as a pair of integers.
//
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
// to the byte-length of the subgroup. This function does not perform that
// truncation itself.
func SignECDSA(curve elliptic.Curve, priv []byte, hash []byte, alg func() hash.Hash) (r, s *big.Int, err error) {
c := curve
N := c.N
D := new(big.Int)
D.SetBytes(priv)
generateSecret(N, D, alg, hash, func(k *big.Int) bool {
inv := new(big.Int).ModInverse(k, N)
r, _ = curve.ScalarBaseMult(k.Bytes())
r.Mod(r, N)
if r.Sign() == 0 {
return false
}
e := hashToInt(hash, c)
s = new(big.Int).Mul(D, r)
s.Add(s, e)
s.Mul(s, inv)
s.Mod(s, N)
return s.Sign() != 0
})
return
}
// copied from crypto/ecdsa
func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
orderBits := c.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
}

View file

@ -1,447 +0,0 @@
package rfc6979_test
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"hash"
"math/big"
"testing"
"github.com/o3labs/neo-utils/neoutils/rfc6979"
)
type ecdsaFixture struct {
name string
key *ecdsaKey
alg func() hash.Hash
message string
r, s string
}
type ecdsaKey struct {
key *ecdsa.PrivateKey
subgroup int
}
var p224 = &ecdsaKey{
key: &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: elliptic.P224(),
X: ecdsaLoadInt("00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C"),
Y: ecdsaLoadInt("EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A"),
},
D: ecdsaLoadInt("F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1"),
},
subgroup: 224,
}
var p256 = &ecdsaKey{
key: &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: elliptic.P256(),
X: ecdsaLoadInt("60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6"),
Y: ecdsaLoadInt("7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299"),
},
D: ecdsaLoadInt("C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721"),
},
subgroup: 256,
}
var p384 = &ecdsaKey{
key: &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: elliptic.P384(),
X: ecdsaLoadInt("EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64DEF8F0EA9055866064A254515480BC13"),
Y: ecdsaLoadInt("8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1288B231C3AE0D4FE7344FD2533264720"),
},
D: ecdsaLoadInt("6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5"),
},
subgroup: 384,
}
var p521 = &ecdsaKey{
key: &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: elliptic.P521(),
X: ecdsaLoadInt("1894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F5023A4"),
Y: ecdsaLoadInt("0493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDFCF5"),
},
D: ecdsaLoadInt("0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538"),
},
subgroup: 521,
}
var fixtures = []ecdsaFixture{
// ECDSA, 224 Bits (Prime Field)
// https://tools.ietf.org/html/rfc6979#appendix-A.2.4
ecdsaFixture{
name: "P224/SHA-1 #1",
key: p224,
alg: sha1.New,
message: "sample",
r: "22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC",
s: "66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69",
},
ecdsaFixture{
name: "P224/SHA-224 #1",
key: p224,
alg: sha256.New224,
message: "sample",
r: "1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E",
s: "A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC",
},
ecdsaFixture{
name: "P224/SHA-256 #1",
key: p224,
alg: sha256.New,
message: "sample",
r: "61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA",
s: "BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101",
},
ecdsaFixture{
name: "P224/SHA-384 #1",
key: p224,
alg: sha512.New384,
message: "sample",
r: "0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953",
s: "830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D",
},
ecdsaFixture{
name: "P224/SHA-512 #1",
key: p224,
alg: sha512.New,
message: "sample",
r: "074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397",
s: "A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084",
},
ecdsaFixture{
name: "P224/SHA-1 #2",
key: p224,
alg: sha1.New,
message: "test",
r: "DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C",
s: "95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2",
},
ecdsaFixture{
name: "P224/SHA-224 #2",
key: p224,
alg: sha256.New224,
message: "test",
r: "C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019",
s: "902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4",
},
ecdsaFixture{
name: "P224/SHA-256 #2",
key: p224,
alg: sha256.New,
message: "test",
r: "AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6",
s: "178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD",
},
ecdsaFixture{
name: "P224/SHA-384 #2",
key: p224,
alg: sha512.New384,
message: "test",
r: "389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4",
s: "414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB",
},
ecdsaFixture{
name: "P224/SHA-512 #2",
key: p224,
alg: sha512.New,
message: "test",
r: "049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C",
s: "077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF",
},
// ECDSA, 256 Bits (Prime Field)
// https://tools.ietf.org/html/rfc6979#appendix-A.2.5
ecdsaFixture{
name: "P256/SHA-1 #1",
key: p256,
alg: sha1.New,
message: "sample",
r: "61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32",
s: "6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB",
},
ecdsaFixture{
name: "P256/SHA-224 #1",
key: p256,
alg: sha256.New224,
message: "sample",
r: "53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F",
s: "B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C",
},
ecdsaFixture{
name: "P256/SHA-256 #1",
key: p256,
alg: sha256.New,
message: "sample",
r: "EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716",
s: "F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8",
},
ecdsaFixture{
name: "P256/SHA-384 #1",
key: p256,
alg: sha512.New384,
message: "sample",
r: "0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719",
s: "4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954",
},
ecdsaFixture{
name: "P256/SHA-512 #1",
key: p256,
alg: sha512.New,
message: "sample",
r: "8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00",
s: "2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE",
},
ecdsaFixture{
name: "P256/SHA-1 #2",
key: p256,
alg: sha1.New,
message: "test",
r: "0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89",
s: "01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1",
},
ecdsaFixture{
name: "P256/SHA-224 #2",
key: p256,
alg: sha256.New224,
message: "test",
r: "C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692",
s: "C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D",
},
ecdsaFixture{
name: "P256/SHA-256 #2",
key: p256,
alg: sha256.New,
message: "test",
r: "F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367",
s: "019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083",
},
ecdsaFixture{
name: "P256/SHA-384 #2",
key: p256,
alg: sha512.New384,
message: "test",
r: "83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6",
s: "8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C",
},
ecdsaFixture{
name: "P256/SHA-512 #2",
key: p256,
alg: sha512.New,
message: "test",
r: "461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04",
s: "39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55",
},
// ECDSA, 384 Bits (Prime Field)
// https://tools.ietf.org/html/rfc6979#appendix-A.2.6
ecdsaFixture{
name: "P384/SHA-1 #1",
key: p384,
alg: sha1.New,
message: "sample",
r: "EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2",
s: "A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443",
},
ecdsaFixture{
name: "P384/SHA-224 #1",
key: p384,
alg: sha256.New224,
message: "sample",
r: "42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE060122",
s: "9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D",
},
ecdsaFixture{
name: "P384/SHA-256 #1",
key: p384,
alg: sha256.New,
message: "sample",
r: "21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD",
s: "F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0",
},
ecdsaFixture{
name: "P384/SHA-384 #1",
key: p384,
alg: sha512.New384,
message: "sample",
r: "94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46",
s: "99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8",
},
ecdsaFixture{
name: "P384/SHA-512 #1",
key: p384,
alg: sha512.New,
message: "sample",
r: "ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709",
s: "512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5",
},
ecdsaFixture{
name: "P384/SHA-1 #2",
key: p384,
alg: sha1.New,
message: "test",
r: "4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7",
s: "D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282",
},
ecdsaFixture{
name: "P384/SHA-224 #2",
key: p384,
alg: sha256.New224,
message: "test",
r: "E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72",
s: "07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66",
},
ecdsaFixture{
name: "P384/SHA-256 #2",
key: p384,
alg: sha256.New,
message: "test",
r: "6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B",
s: "2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265",
},
ecdsaFixture{
name: "P384/SHA-384 #2",
key: p384,
alg: sha512.New384,
message: "test",
r: "8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB",
s: "DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5",
},
ecdsaFixture{
name: "P384/SHA-512 #2",
key: p384,
alg: sha512.New,
message: "test",
r: "A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277",
s: "976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736",
},
// ECDSA, 521 Bits (Prime Field)
// https://tools.ietf.org/html/rfc6979#appendix-A.2.7
ecdsaFixture{
name: "P521/SHA-1 #1",
key: p521,
alg: sha1.New,
message: "sample",
r: "0343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D",
s: "0E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16",
},
ecdsaFixture{
name: "P521/SHA-224 #1",
key: p521,
alg: sha256.New224,
message: "sample",
r: "1776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E",
s: "050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F",
},
ecdsaFixture{
name: "P521/SHA-256 #1",
key: p521,
alg: sha256.New,
message: "sample",
r: "1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7",
s: "04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC",
},
ecdsaFixture{
name: "P521/SHA-384 #1",
key: p521,
alg: sha512.New384,
message: "sample",
r: "1EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451",
s: "1F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61",
},
ecdsaFixture{
name: "P521/SHA-512 #1",
key: p521,
alg: sha512.New,
message: "sample",
r: "0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA",
s: "0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A",
},
ecdsaFixture{
name: "P521/SHA-1 #2",
key: p521,
alg: sha1.New,
message: "test",
r: "13BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367",
s: "1E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF",
},
ecdsaFixture{
name: "P521/SHA-224 #2",
key: p521,
alg: sha256.New224,
message: "test",
r: "1C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB",
s: "177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4",
},
ecdsaFixture{
name: "P521/SHA-256 #2",
key: p521,
alg: sha256.New,
message: "test",
r: "00E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8",
s: "0CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86",
},
ecdsaFixture{
name: "P521/SHA-384 #2",
key: p521,
alg: sha512.New384,
message: "test",
r: "14BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C",
s: "133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979",
},
ecdsaFixture{
name: "P521/SHA-512 #2",
key: p521,
alg: sha512.New,
message: "test",
r: "13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D",
s: "1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3",
},
}
func TestECDSA(t *testing.T) {
for _, f := range fixtures {
testEcsaFixture(&f, t)
}
}
func ecdsaLoadInt(s string) (n *big.Int) {
n, _ = new(big.Int).SetString(s, 16)
return
}
func testEcsaFixture(f *ecdsaFixture, t *testing.T) {
t.Logf("Testing %s", f.name)
h := f.alg()
h.Write([]byte(f.message))
digest := h.Sum(nil)
g := f.key.subgroup / 8
if len(digest) > g {
digest = digest[0:g]
}
r, s, err := rfc6979.SignECDSA(f.key.key, digest, f.alg)
if err != nil {
t.Error(err)
return
}
expectedR := ecdsaLoadInt(f.r)
expectedS := ecdsaLoadInt(f.s)
if r.Cmp(expectedR) != 0 {
t.Errorf("%s: Expected R of %X, got %X", f.name, expectedR, r)
}
if s.Cmp(expectedS) != 0 {
t.Errorf("%s: Expected S of %X, got %X", f.name, expectedS, s)
}
}

View file

@ -1,76 +0,0 @@
package rfc6979
import (
"crypto/dsa"
"crypto/ecdsa"
"crypto/rand"
"crypto/sha1"
"crypto/sha512"
"fmt"
"github.com/CityOfZion/neo-go/pkg/crypto/elliptic"
)
// Generates a 521-bit ECDSA key, uses SHA-512 to sign a message, then verifies
// it.
func ExampleSignECDSA() {
// Generate a key pair.
// You need a high-quality PRNG for this.
curve := elliptic.NewEllipticCurve(elliptic.Secp256r1)
k, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
fmt.Println(err)
return
}
// Hash a message.
alg := sha512.New()
_, _ = alg.Write([]byte("I am a potato."))
hash := alg.Sum(nil)
// Sign the message. You don't need a PRNG for this.
r, s, err := SignECDSA(curve, k.D.Bytes(), hash, sha512.New)
if err != nil {
fmt.Println(err)
return
}
if !ecdsa.Verify(&k.PublicKey, hash, r, s) {
fmt.Println("Invalid signature!")
}
}
// Generates a 1024-bit DSA key, uses SHA-1 to sign a message, then verifies it.
func ExampleSignDSA() {
// Here I'm generating some DSA params, but you should really pre-generate
// these and re-use them, since this takes a long time and isn't necessary.
k := new(dsa.PrivateKey)
dsa.GenerateParameters(&k.Parameters, rand.Reader, dsa.L1024N160)
// Generate a key pair.
// You need a high-quality PRNG for this.
err := dsa.GenerateKey(k, rand.Reader)
if err != nil {
fmt.Println(err)
return
}
// Hash a message.
alg := sha1.New()
_, _ = alg.Write([]byte("I am a potato."))
hash := alg.Sum(nil)
// Sign the message. You don't need a PRNG for this.
r, s, err := SignDSA(k, hash, sha1.New)
if err != nil {
fmt.Println(err)
return
}
if !dsa.Verify(&k.PublicKey, hash, r, s) {
fmt.Println("Invalid signature!")
}
}

View file

@ -1,119 +0,0 @@
/*
Package rfc6979 is an implementation of RFC 6979's deterministic DSA.
Such signatures are compatible with standard Digital Signature Algorithm
(DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA) digital
signatures and can be processed with unmodified verifiers, which need not be
aware of the procedure described therein. Deterministic signatures retain
the cryptographic security features associated with digital signatures but
can be more easily implemented in various environments, since they do not
need access to a source of high-quality randomness.
(https://tools.ietf.org/html/rfc6979)
Provides functions similar to crypto/dsa and crypto/ecdsa.
*/
package rfc6979
import (
"bytes"
"crypto/hmac"
"hash"
"math/big"
)
// mac returns an HMAC of the given key and message.
func mac(alg func() hash.Hash, k, m, buf []byte) []byte {
h := hmac.New(alg, k)
h.Write(m)
return h.Sum(buf[:0])
}
// https://tools.ietf.org/html/rfc6979#section-2.3.2
func bits2int(in []byte, qlen int) *big.Int {
vlen := len(in) * 8
v := new(big.Int).SetBytes(in)
if vlen > qlen {
v = new(big.Int).Rsh(v, uint(vlen-qlen))
}
return v
}
// https://tools.ietf.org/html/rfc6979#section-2.3.3
func int2octets(v *big.Int, rolen int) []byte {
out := v.Bytes()
// 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, q *big.Int, qlen, rolen int) []byte {
z1 := bits2int(in, qlen)
z2 := new(big.Int).Sub(z1, q)
if z2.Sign() < 0 {
return int2octets(z1, rolen)
}
return int2octets(z2, rolen)
}
var one = big.NewInt(1)
// https://tools.ietf.org/html/rfc6979#section-3.2
func generateSecret(q, x *big.Int, alg func() hash.Hash, hash []byte, test func(*big.Int) bool) {
qlen := q.BitLen()
holen := alg().Size()
rolen := (qlen + 7) >> 3
bx := append(int2octets(x, rolen), bits2octets(hash, q, qlen, rolen)...)
// Step B
v := bytes.Repeat([]byte{0x01}, holen)
// Step C
k := bytes.Repeat([]byte{0x00}, holen)
// Step D
k = mac(alg, k, append(append(v, 0x00), bx...), k)
// Step E
v = mac(alg, k, v, v)
// Step F
k = mac(alg, k, append(append(v, 0x01), bx...), k)
// Step G
v = mac(alg, k, v, v)
// Step H
for {
// Step H1
var t []byte
// Step H2
for len(t) < qlen/8 {
v = mac(alg, k, v, v)
t = append(t, v...)
}
// Step H3
secret := bits2int(t, qlen)
if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 && test(secret) {
return
}
k = mac(alg, k, append(v, 0x00), k)
v = mac(alg, k, v, v)
}
}

View file

@ -1,28 +0,0 @@
package rfc6979
import (
"crypto/sha256"
"encoding/hex"
"math/big"
"testing"
)
// https://tools.ietf.org/html/rfc6979#appendix-A.1
func TestGenerateSecret(t *testing.T) {
q, _ := new(big.Int).SetString("4000000000000000000020108A2E0CC0D99F8A5EF", 16)
x, _ := new(big.Int).SetString("09A4D6792295A7F730FC3F2B49CBC0F62E862272F", 16)
hash, _ := hex.DecodeString("AF2BDBE1AA9B6EC1E2ADE1D694F41FC71A831D0268E9891562113D8A62ADD1BF")
expected, _ := new(big.Int).SetString("23AF4074C90A02B3FE61D286D5C87F425E6BDD81B", 16)
var actual *big.Int
generateSecret(q, x, sha256.New, hash, func(k *big.Int) bool {
actual = k
return true
})
if actual.Cmp(expected) != 0 {
t.Errorf("Expected %x, got %x", expected, actual)
}
}

View file

@ -1,62 +0,0 @@
package fixed8
import (
"errors"
"fmt"
"strconv"
)
const (
decimals = 100000000
)
var errInvalidString = errors.New("Fixed8 must satisfy following regex \\d+(\\.\\d{1,8})?")
// Fixed8 represents a fixed-point number with precision 10^-8.
type Fixed8 int64
// String implements the Stringer interface.
func (f Fixed8) String() string {
val := f.Value()
return strconv.FormatFloat(val, 'f', -1, 64)
}
// Value returns the original value representing the Fixed8.
func (f Fixed8) Value() float64 {
return float64(f) / float64(decimals)
}
// Add adds two Fixed8 values together
func (f Fixed8) Add(val Fixed8) Fixed8 {
a := int64(f.Value())
b := int64(val.Value())
c := a + b
return FromInt(c)
}
//Sub subtracts two fixed values from each other
func (f Fixed8) Sub(val Fixed8) Fixed8 {
a := int64(f.Value())
b := int64(val.Value())
c := a - b
return FromInt(c)
}
//FromInt returns a Fixed8 objects from an int64
func FromInt(val int64) Fixed8 {
return Fixed8(val * decimals)
}
// FromFloat returns a Fixed8 object from a float64
func FromFloat(val float64) Fixed8 {
return Fixed8(val * decimals)
}
// FromString returns a Fixed8 object from a string
func FromString(val string) (Fixed8, error) {
res, err := strconv.ParseFloat(val, 64)
if err != nil {
return 0, fmt.Errorf("failed at parsing string %s", val)
}
return FromFloat(res), nil
}

View file

@ -1,85 +0,0 @@
package fixed8
import (
"strconv"
"testing"
"github.com/stretchr/testify/assert"
)
func TestFixed8Value(t *testing.T) {
input := int64(12)
assert.Equal(t, float64(input), FromInt(input).Value())
}
func TestFixed8Add(t *testing.T) {
a := FromInt(1)
b := FromInt(2)
c := a.Add(b)
expected := float64(3)
assert.Equal(t, expected, c.Value())
}
func TestFixed8AddRecursive(t *testing.T) {
a := FromInt(1)
sum := int64(1)
for i := int64(2); i <= 10; i++ {
sum += i
b := FromInt(i)
c := a.Add(b)
a = c // 1 + 2 + 3 ... + 10
}
assert.Equal(t, float64(sum), a.Value())
}
func TestFromInt(t *testing.T) {
inputs := []int64{12, 23, 100, 456789}
for _, val := range inputs {
assert.Equal(t, Fixed8(val*decimals), FromInt(val))
assert.Equal(t, float64(val), FromInt(val).Value())
}
for _, val := range inputs {
valString := strconv.FormatInt(val, 10)
assert.Equal(t, valString, FromInt(val).String())
}
}
func TestFromFloat(t *testing.T) {
inputs := []float64{12.98, 23.87654333, 100.654322, 456789.12345665}
for _, val := range inputs {
assert.Equal(t, Fixed8(val*decimals), FromFloat(val))
assert.Equal(t, float64(val), FromFloat(val).Value())
}
}
func TestFromString(t *testing.T) {
inputs := []string{"9000", "100000000", "5", "10945", "20.45", "0.00000001"}
for _, val := range inputs {
n, err := FromString(val)
assert.Nil(t, err)
assert.Equal(t, val, n.String())
}
val := "123456789.12345678"
n, err := FromString(val)
assert.Nil(t, err)
assert.Equal(t, Fixed8(12345678912345678), n)
val = "901.2341"
n, err = FromString(val)
assert.Nil(t, err)
assert.Equal(t, Fixed8(90123410000), n)
}

View file

@ -1,15 +0,0 @@
package slice
// Reverse return a reversed version of the given byte slice.
func Reverse(b []byte) []byte {
// Protect from big.Ints that have 1 len bytes.
if len(b) < 2 {
return b
}
dest := make([]byte, len(b))
for i, j := 0, len(b)-1; i < j+1; i, j = i+1, j-1 {
dest[i], dest[j] = b[j], b[i]
}
return dest
}

View file

@ -1,33 +0,0 @@
package slice
import (
"bytes"
"testing"
)
func TestSliceReverse(t *testing.T) {
arr := []byte{0x01, 0x02, 0x03, 0x04}
have := Reverse(arr)
want := []byte{0x04, 0x03, 0x02, 0x01}
if bytes.Compare(have, want) != 0 {
t.Fatalf("expected %v got %v", want, have)
}
}
func TestSliceReverseOddNumberOfElements(t *testing.T) {
arr := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
have := Reverse(arr)
want := []byte{0x05, 0x04, 0x03, 0x02, 0x01}
if bytes.Compare(have, want) != 0 {
t.Fatalf("expected %v got %v", want, have)
}
}
// This tests a bug that occured with arrays of size 1
func TestSliceReverseLen2(t *testing.T) {
arr := []byte{0x01}
have := Reverse(arr)
want := []byte{0x01}
if bytes.Compare(have, want) != 0 {
t.Fatalf("expected %v got %v", want, have)
}
}

View file

@ -1,91 +0,0 @@
package util
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/CityOfZion/neo-go/pkg/wire/util/slice"
"golang.org/x/crypto/ripemd160"
)
const uint160Size = 20
// Uint160 is a 20 byte long unsigned integer.
type Uint160 [uint160Size]uint8
// Uint160DecodeString attempts to decode the given string into an Uint160.
func Uint160DecodeString(s string) (u Uint160, err error) {
if len(s) != uint160Size*2 {
return u, fmt.Errorf("expected string size of %d got %d", uint160Size*2, len(s))
}
b, err := hex.DecodeString(s)
if err != nil {
return u, err
}
return Uint160DecodeBytes(b)
}
// Uint160DecodeBytes attempts to decode the given bytes into an Uint160.
func Uint160DecodeBytes(b []byte) (u Uint160, err error) {
if len(b) != uint160Size {
return u, fmt.Errorf("expected byte size of %d got %d", uint160Size, len(b))
}
for i := 0; i < uint160Size; i++ {
u[i] = b[i]
}
return
}
// Uint160FromScript returns a Uint160 type from a raw script.
func Uint160FromScript(script []byte) (u Uint160, err error) {
sha := sha256.New()
sha.Write(script)
b := sha.Sum(nil)
ripemd := ripemd160.New()
ripemd.Write(b)
b = ripemd.Sum(nil)
return Uint160DecodeBytes(b)
}
// Bytes returns the byte slice representation of u.
func (u Uint160) Bytes() []byte {
b := make([]byte, uint160Size)
for i := 0; i < uint160Size; i++ {
b[i] = byte(u[i])
}
return b
}
// BytesReverse return a reversed byte representation of u.
func (u Uint160) BytesReverse() []byte {
return slice.Reverse(u.Bytes())
}
// String implements the stringer interface.
func (u Uint160) String() string {
return hex.EncodeToString(u.Bytes())
}
// ReverseString implements the stringer interface.
func (u Uint160) ReverseString() string {
return hex.EncodeToString(u.BytesReverse())
}
// Equals returns true if both Uint256 values are the same.
func (u Uint160) Equals(other Uint160) bool {
for i := 0; i < uint160Size; i++ {
if u[i] != other[i] {
return false
}
}
return true
}
// MarshalJSON implements the json marshaller interface.
func (u Uint160) MarshalJSON() ([]byte, error) {
return json.Marshal(
fmt.Sprintf("0x%s", hex.EncodeToString(slice.Reverse(u.Bytes()))),
)
}

View file

@ -1,62 +0,0 @@
package util
import (
"encoding/hex"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUInt160DecodeString(t *testing.T) {
hexStr := "2d3b96ae1bcc5a585e075e3b81920210dec16302"
val, err := Uint160DecodeString(hexStr)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, hexStr, val.String())
}
func TestUint160DecodeBytes(t *testing.T) {
hexStr := "2d3b96ae1bcc5a585e075e3b81920210dec16302"
b, err := hex.DecodeString(hexStr)
if err != nil {
t.Fatal(err)
}
val, err := Uint160DecodeBytes(b)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, hexStr, val.String())
}
func TestUInt160Equals(t *testing.T) {
a := "2d3b96ae1bcc5a585e075e3b81920210dec16302"
b := "4d3b96ae1bcc5a585e075e3b81920210dec16302"
ua, err := Uint160DecodeString(a)
if err != nil {
t.Fatal(err)
}
ub, err := Uint160DecodeString(b)
if err != nil {
t.Fatal(err)
}
if ua.Equals(ub) {
t.Fatalf("%s and %s cannot be equal", ua, ub)
}
if !ua.Equals(ua) {
t.Fatalf("%s and %s must be equal", ua, ua)
}
}
func TestUInt160String(t *testing.T) {
hexStr := "b28427088a3729b2536d10122960394e8be6721f"
hexRevStr := "1f72e68b4e39602912106d53b229378a082784b2"
val, err := Uint160DecodeString(hexStr)
assert.Nil(t, err)
assert.Equal(t, hexStr, val.String())
assert.Equal(t, hexRevStr, val.ReverseString())
}

View file

@ -1,77 +0,0 @@
package util
import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/CityOfZion/neo-go/pkg/wire/util/slice"
)
const uint256Size = 32
// Uint256 is a 32 byte long unsigned integer.
type Uint256 [uint256Size]uint8
// Uint256DecodeString attempts to decode the given string into an Uint256.
func Uint256DecodeString(s string) (u Uint256, err error) {
if len(s) != uint256Size*2 {
return u, fmt.Errorf("expected string size of %d got %d", uint256Size*2, len(s))
}
b, err := hex.DecodeString(s)
if err != nil {
return u, err
}
return Uint256DecodeBytes(b)
}
// Uint256DecodeBytes attempts to decode the given string into an Uint256.
func Uint256DecodeBytes(b []byte) (u Uint256, err error) {
if len(b) != uint256Size {
return u, fmt.Errorf("expected []byte of size %d got %d", uint256Size, len(b))
}
for i := 0; i < uint256Size; i++ {
u[i] = b[i]
}
return u, nil
}
// Bytes returns a byte slice representation of u.
func (u Uint256) Bytes() []byte {
b := make([]byte, uint256Size)
for i := 0; i < uint256Size; i++ {
b[i] = byte(u[i])
}
return b
}
// Reverse reverses the Uint256 object
func (u Uint256) Reverse() Uint256 {
res, _ := Uint256DecodeBytes(u.BytesReverse())
return res
}
// BytesReverse return a reversed byte representation of u.
func (u Uint256) BytesReverse() []byte {
return slice.Reverse(u.Bytes())
}
// Equals returns true if both Uint256 values are the same.
func (u Uint256) Equals(other Uint256) bool {
return u.String() == other.String()
}
// String implements the stringer interface.
func (u Uint256) String() string {
return hex.EncodeToString(u.Bytes())
}
// ReverseString displays a reverse string representation of Uint256.
func (u Uint256) ReverseString() string {
return hex.EncodeToString(slice.Reverse(u.Bytes()))
}
// MarshalJSON implements the json marshaller interface.
func (u Uint256) MarshalJSON() ([]byte, error) {
return json.Marshal(fmt.Sprintf("0x%s", u.String()))
}

View file

@ -1,50 +0,0 @@
package util
import (
"encoding/hex"
"testing"
"github.com/stretchr/testify/assert"
)
func TestUint256DecodeString(t *testing.T) {
hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
val, err := Uint256DecodeString(hexStr)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, hexStr, val.String())
}
func TestUint256DecodeBytes(t *testing.T) {
hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
b, err := hex.DecodeString(hexStr)
if err != nil {
t.Fatal(err)
}
val, err := Uint256DecodeBytes(b)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, hexStr, val.String())
}
func TestUInt256Equals(t *testing.T) {
a := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
b := "e287c5b29a1b66092be6803c59c765308ac20287e1b4977fd399da5fc8f66ab5"
ua, err := Uint256DecodeString(a)
if err != nil {
t.Fatal(err)
}
ub, err := Uint256DecodeString(b)
if err != nil {
t.Fatal(err)
}
if ua.Equals(ub) {
t.Fatalf("%s and %s cannot be equal", ua, ub)
}
if !ua.Equals(ua) {
t.Fatalf("%s and %s must be equal", ua, ua)
}
}

View file

@ -127,14 +127,14 @@ func Load(path string, netMode NetMode) (Config, error) {
func (s SystemFee) TryGetValue(txType transaction.TXType) util.Fixed8 { func (s SystemFee) TryGetValue(txType transaction.TXType) util.Fixed8 {
switch txType { switch txType {
case transaction.EnrollmentType: case transaction.EnrollmentType:
return util.NewFixed8(s.EnrollmentTransaction) return util.Fixed8FromInt64(s.EnrollmentTransaction)
case transaction.IssueType: case transaction.IssueType:
return util.NewFixed8(s.IssueTransaction) return util.Fixed8FromInt64(s.IssueTransaction)
case transaction.PublishType: case transaction.PublishType:
return util.NewFixed8(s.PublishTransaction) return util.Fixed8FromInt64(s.PublishTransaction)
case transaction.RegisterType: case transaction.RegisterType:
return util.NewFixed8(s.RegisterTransaction) return util.Fixed8FromInt64(s.RegisterTransaction)
default: default:
return util.NewFixed8(0) return util.Fixed8FromInt64(0)
} }
} }

View file

@ -16,7 +16,7 @@ func TestDecodeEncodeAccountState(t *testing.T) {
votes = make([]*crypto.PublicKey, n) votes = make([]*crypto.PublicKey, n)
) )
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
balances[util.RandomUint256()] = util.Fixed8(int64(util.RandomInt(1, 10000))) balances[randomUint256()] = util.Fixed8(int64(randomInt(1, 10000)))
votes[i] = &crypto.PublicKey{ votes[i] = &crypto.PublicKey{
ECPoint: crypto.RandomECPoint(), ECPoint: crypto.RandomECPoint(),
} }
@ -24,7 +24,7 @@ func TestDecodeEncodeAccountState(t *testing.T) {
a := &AccountState{ a := &AccountState{
Version: 0, Version: 0,
ScriptHash: util.RandomUint160(), ScriptHash: randomUint160(),
IsFrozen: true, IsFrozen: true,
Votes: votes, Votes: votes,
Balances: balances, Balances: balances,

View file

@ -12,7 +12,7 @@ import (
func TestEncodeDecodeAssetState(t *testing.T) { func TestEncodeDecodeAssetState(t *testing.T) {
asset := &AssetState{ asset := &AssetState{
ID: util.RandomUint256(), ID: randomUint256(),
AssetType: transaction.Token, AssetType: transaction.Token,
Name: "super cool token", Name: "super cool token",
Amount: util.Fixed8(1000000), Amount: util.Fixed8(1000000),
@ -20,8 +20,8 @@ func TestEncodeDecodeAssetState(t *testing.T) {
Precision: 0, Precision: 0,
FeeMode: feeMode, FeeMode: feeMode,
Owner: &crypto.PublicKey{}, Owner: &crypto.PublicKey{},
Admin: util.RandomUint160(), Admin: randomUint160(),
Issuer: util.RandomUint160(), Issuer: randomUint160(),
Expiration: 10, Expiration: 10,
IsFrozen: false, IsFrozen: false,
} }

View file

@ -2,12 +2,12 @@ package core
import ( import (
"bytes" "bytes"
"crypto/sha256"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -100,12 +100,7 @@ func (b *BlockBase) createHash() error {
if err := b.encodeHashableFields(buf); err != nil { if err := b.encodeHashableFields(buf); err != nil {
return err return err
} }
b.hash = hash.DoubleSha256(buf.Bytes())
// Double hash the encoded fields.
var hash util.Uint256
hash = sha256.Sum256(buf.Bytes())
hash = sha256.Sum256(hash.Bytes())
b.hash = hash
return nil return nil
} }

View file

@ -30,9 +30,9 @@ func TestDecodeBlock1(t *testing.T) {
assert.Equal(t, uint32(data["index"].(float64)), block.Index) assert.Equal(t, uint32(data["index"].(float64)), block.Index)
assert.Equal(t, uint32(data["version"].(float64)), block.Version) assert.Equal(t, uint32(data["version"].(float64)), block.Version)
assert.Equal(t, data["hash"].(string), block.Hash().String()) assert.Equal(t, data["hash"].(string), block.Hash().ReverseString())
assert.Equal(t, data["previousblockhash"].(string), block.PrevHash.String()) assert.Equal(t, data["previousblockhash"].(string), block.PrevHash.ReverseString())
assert.Equal(t, data["merkleroot"].(string), block.MerkleRoot.String()) assert.Equal(t, data["merkleroot"].(string), block.MerkleRoot.ReverseString())
assert.Equal(t, data["nextconsensus"].(string), crypto.AddressFromUint160(block.NextConsensus)) assert.Equal(t, data["nextconsensus"].(string), crypto.AddressFromUint160(block.NextConsensus))
script := data["script"].(map[string]interface{}) script := data["script"].(map[string]interface{})

View file

@ -635,14 +635,14 @@ func (bc *Blockchain) FeePerByte(t *transaction.Transaction) util.Fixed8 {
// NetworkFee returns network fee // NetworkFee returns network fee
func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 { func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
inputAmount := util.NewFixed8(0) inputAmount := util.Fixed8FromInt64(0)
for _, txOutput := range bc.References(t) { for _, txOutput := range bc.References(t) {
if txOutput.AssetID == utilityTokenTX().Hash() { if txOutput.AssetID == utilityTokenTX().Hash() {
inputAmount.Add(txOutput.Amount) inputAmount.Add(txOutput.Amount)
} }
} }
outputAmount := util.NewFixed8(0) outputAmount := util.Fixed8FromInt64(0)
for _, txOutput := range t.Outputs { for _, txOutput := range t.Outputs {
if txOutput.AssetID == utilityTokenTX().Hash() { if txOutput.AssetID == utilityTokenTX().Hash() {
outputAmount.Add(txOutput.Amount) outputAmount.Add(txOutput.Amount)
@ -660,7 +660,7 @@ func (bc *Blockchain) SystemFee(t *transaction.Transaction) util.Fixed8 {
// IsLowPriority flags a trnsaction as low priority if the network fee is less than // IsLowPriority flags a trnsaction as low priority if the network fee is less than
// LowPriorityThreshold // LowPriorityThreshold
func (bc *Blockchain) IsLowPriority(t *transaction.Transaction) bool { func (bc *Blockchain) IsLowPriority(t *transaction.Transaction) bool {
return bc.NetworkFee(t) < util.NewFixed8FromFloat(bc.GetConfig().LowPriorityThreshold) return bc.NetworkFee(t) < util.Fixed8FromFloat(bc.GetConfig().LowPriorityThreshold)
} }
// GetMemPool returns the memory pool of the blockchain. // GetMemPool returns the memory pool of the blockchain.
@ -906,8 +906,8 @@ func (bc *Blockchain) VerifyWitnesses(t *transaction.Transaction) error {
*/ */
} else { } else {
if h, err := witnesses[i].ScriptHash(); err != nil || hashes[i] != h { if h := witnesses[i].ScriptHash(); hashes[i] != h {
return err return errors.Errorf("hash mismatch for script #%d", i)
} }
} }

View file

@ -185,7 +185,7 @@ func getTestBlockchain(t *testing.T) *Blockchain {
func getTestTransaction(txID string, t *testing.T) *transaction.Transaction { func getTestTransaction(txID string, t *testing.T) *transaction.Transaction {
chain := getTestBlockchain(t) chain := getTestBlockchain(t)
txHash, err := util.Uint256DecodeString(txID) txHash, err := util.Uint256DecodeReverseString(txID)
require.NoErrorf(t, err, "could not decode string %s to Uint256", txID) require.NoErrorf(t, err, "could not decode string %s to Uint256", txID)
tx, _, err := chain.GetTransaction(txHash) tx, _, err := chain.GetTransaction(txHash)

View file

@ -2,19 +2,19 @@ package core
import ( import (
"bytes" "bytes"
"crypto/sha256"
"testing" "testing"
"time" "time"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
func TestHeaderEncodeDecode(t *testing.T) { func TestHeaderEncodeDecode(t *testing.T) {
header := Header{BlockBase: BlockBase{ header := Header{BlockBase: BlockBase{
Version: 0, Version: 0,
PrevHash: sha256.Sum256([]byte("prevhash")), PrevHash: hash.Sha256([]byte("prevhash")),
MerkleRoot: sha256.Sum256([]byte("merkleroot")), MerkleRoot: hash.Sha256([]byte("merkleroot")),
Timestamp: uint32(time.Now().UTC().Unix()), Timestamp: uint32(time.Now().UTC().Unix()),
Index: 3445, Index: 3445,
ConsensusData: 394949, ConsensusData: 394949,

View file

@ -2,7 +2,6 @@ package core
import ( import (
"bytes" "bytes"
"crypto/sha256"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -11,6 +10,7 @@ import (
"time" "time"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -18,8 +18,8 @@ func newBlock(index uint32, txs ...*transaction.Transaction) *Block {
b := &Block{ b := &Block{
BlockBase: BlockBase{ BlockBase: BlockBase{
Version: 0, Version: 0,
PrevHash: sha256.Sum256([]byte("a")), PrevHash: hash.Sha256([]byte("a")),
MerkleRoot: sha256.Sum256([]byte("b")), MerkleRoot: hash.Sha256([]byte("b")),
Timestamp: uint32(time.Now().UTC().Unix()), Timestamp: uint32(time.Now().UTC().Unix()),
Index: index, Index: index,
ConsensusData: 1111, ConsensusData: 1111,

View file

@ -0,0 +1,40 @@
package core
import (
"math/rand"
"time"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util"
)
// RandomString returns a random string with the n as its length.
func randomString(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = byte(randomInt(65, 90))
}
return string(b)
}
// RandomInt returns a random integer between min and max.
func randomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// RandomUint256 returns a random Uint256.
func randomUint256() util.Uint256 {
str := randomString(20)
return hash.Sha256([]byte(str))
}
// RandomUint160 returns a random Uint160.
func randomUint160() util.Uint160 {
str := randomString(20)
return hash.RipeMD160([]byte(str))
}
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}

View file

@ -11,7 +11,7 @@ import (
func TestEncodeDecodeSpentCoinState(t *testing.T) { func TestEncodeDecodeSpentCoinState(t *testing.T) {
spent := &SpentCoinState{ spent := &SpentCoinState{
txHash: util.RandomUint256(), txHash: randomUint256(),
txHeight: 1001, txHeight: 1001,
items: map[uint16]uint32{ items: map[uint16]uint32{
1: 3, 1: 3,
@ -35,9 +35,9 @@ func TestCommitSpentCoins(t *testing.T) {
) )
txx := []util.Uint256{ txx := []util.Uint256{
util.RandomUint256(), randomUint256(),
util.RandomUint256(), randomUint256(),
util.RandomUint256(), randomUint256(),
} }
for i := 0; i < len(txx); i++ { for i := 0; i < len(txx); i++ {

View file

@ -38,7 +38,7 @@ func CurrentHeaderHeight(s Store) (i uint32, h util.Uint256, err error) {
return return
} }
i = binary.LittleEndian.Uint32(b[32:36]) i = binary.LittleEndian.Uint32(b[32:36])
h, err = util.Uint256DecodeBytes(b[:32]) h, err = util.Uint256DecodeReverseBytes(b[:32])
return return
} }

View file

@ -11,16 +11,17 @@ import (
) )
func TestRegisterTX(t *testing.T) { func TestRegisterTX(t *testing.T) {
someuint160, _ := util.Uint160DecodeString("4d3b96ae1bcc5a585e075e3b81920210dec16302")
tx := &Transaction{ tx := &Transaction{
Type: RegisterType, Type: RegisterType,
Version: 0, Version: 0,
Data: &RegisterTX{ Data: &RegisterTX{
AssetType: UtilityToken, AssetType: UtilityToken,
Name: "this is some token I created", Name: "this is some token I created",
Amount: util.NewFixed8(1000000), Amount: util.Fixed8FromInt64(1000000),
Precision: 8, Precision: 8,
Owner: &crypto.PublicKey{}, Owner: &crypto.PublicKey{},
Admin: util.RandomUint160(), Admin: someuint160,
}, },
} }
@ -48,11 +49,11 @@ func TestDecodeRegisterTXFromRawString(t *testing.T) {
txData := tx.Data.(*RegisterTX) txData := tx.Data.(*RegisterTX)
assert.Equal(t, GoverningToken, txData.AssetType) assert.Equal(t, GoverningToken, txData.AssetType)
assert.Equal(t, "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]", txData.Name) assert.Equal(t, "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]", txData.Name)
assert.Equal(t, util.NewFixed8(100000000), txData.Amount) assert.Equal(t, util.Fixed8FromInt64(100000000), txData.Amount)
assert.Equal(t, uint8(0), txData.Precision) assert.Equal(t, uint8(0), txData.Precision)
assert.Equal(t, &crypto.PublicKey{}, txData.Owner) assert.Equal(t, &crypto.PublicKey{}, txData.Owner)
assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", crypto.AddressFromUint160(txData.Admin)) assert.Equal(t, "Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt", crypto.AddressFromUint160(txData.Admin))
assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().String()) assert.Equal(t, "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", tx.Hash().ReverseString())
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
assert.Nil(t, tx.EncodeBinary(buf)) assert.Nil(t, tx.EncodeBinary(buf))

View file

@ -2,10 +2,10 @@ package transaction
import ( import (
"bytes" "bytes"
"crypto/sha256"
"encoding/binary" "encoding/binary"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -240,10 +240,7 @@ func (t *Transaction) createHash() error {
return err return err
} }
var hash util.Uint256 t.hash = hash.DoubleSha256(buf.Bytes())
hash = sha256.Sum256(buf.Bytes())
hash = sha256.Sum256(hash.Bytes())
t.hash = hash
return nil return nil
} }

View file

@ -59,7 +59,7 @@ func TestDecodeEncodeClaimTX(t *testing.T) {
assert.Equal(t, 1, len(tx.Outputs)) assert.Equal(t, 1, len(tx.Outputs))
address := crypto.AddressFromUint160(tx.Outputs[0].ScriptHash) address := crypto.AddressFromUint160(tx.Outputs[0].ScriptHash)
assert.Equal(t, "AQJseD8iBmCD4sgfHRhMahmoi9zvopG6yz", address) assert.Equal(t, "AQJseD8iBmCD4sgfHRhMahmoi9zvopG6yz", address)
assert.Equal(t, "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", tx.Outputs[0].AssetID.String()) assert.Equal(t, "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", tx.Outputs[0].AssetID.ReverseString())
assert.Equal(t, tx.Outputs[0].Amount.String(), "0.06247739") assert.Equal(t, tx.Outputs[0].Amount.String(), "0.06247739")
invoc := "40456349cec43053009accdb7781b0799c6b591c812768804ab0a0b56b5eae7a97694227fcd33e70899c075848b2cee8fae733faac6865b484d3f7df8949e2aadb" invoc := "40456349cec43053009accdb7781b0799c6b591c812768804ab0a0b56b5eae7a97694227fcd33e70899c075848b2cee8fae733faac6865b484d3f7df8949e2aadb"
verif := "2103945fae1ed3c31d778f149192b76734fcc951b400ba3598faa81ff92ebe477eacac" verif := "2103945fae1ed3c31d778f149192b76734fcc951b400ba3598faa81ff92ebe477eacac"
@ -74,7 +74,7 @@ func TestDecodeEncodeClaimTX(t *testing.T) {
assert.Equal(t, rawClaimTX, hex.EncodeToString(buf.Bytes())) assert.Equal(t, rawClaimTX, hex.EncodeToString(buf.Bytes()))
hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da" hash := "2c6a45547b3898318e400e541628990a07acb00f3b9a15a8e966ae49525304da"
assert.Equal(t, hash, tx.hash.String()) assert.Equal(t, hash, tx.hash.ReverseString())
} }
func TestDecodeEncodeInvocationTX(t *testing.T) { func TestDecodeEncodeInvocationTX(t *testing.T) {

View file

@ -6,6 +6,7 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -57,6 +58,6 @@ func (w *Witness) Size() int {
} }
// ScriptHash returns the hash of the VerificationScript. // ScriptHash returns the hash of the VerificationScript.
func (w Witness) ScriptHash() (util.Uint160, error) { func (w Witness) ScriptHash() util.Uint160 {
return util.Uint160FromScript(w.VerificationScript) return hash.Hash160(w.VerificationScript)
} }

View file

@ -5,7 +5,6 @@ import (
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -33,9 +32,9 @@ func TestCommitUnspentCoins(t *testing.T) {
unspentCoins = make(UnspentCoins) unspentCoins = make(UnspentCoins)
) )
txA := util.RandomUint256() txA := randomUint256()
txB := util.RandomUint256() txB := randomUint256()
txC := util.RandomUint256() txC := randomUint256()
unspentCoins[txA] = &UnspentCoinState{ unspentCoins[txA] = &UnspentCoinState{
states: []CoinState{CoinStateConfirmed}, states: []CoinState{CoinStateConfirmed},

View file

@ -9,6 +9,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/core/storage" "github.com/CityOfZion/neo-go/pkg/core/storage"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/smartcontract" "github.com/CityOfZion/neo-go/pkg/smartcontract"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/CityOfZion/neo-go/pkg/vm" "github.com/CityOfZion/neo-go/pkg/vm"
@ -48,10 +49,7 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
scriptOut, err := util.Uint160FromScript(rawScript) scriptOut := hash.Hash160(rawScript)
if err != nil {
return nil, err
}
block := &Block{ block := &Block{
BlockBase: base, BlockBase: base,
@ -97,11 +95,11 @@ func createGenesisBlock(cfg config.ProtocolConfiguration) (*Block, error) {
} }
func governingTokenTX() *transaction.Transaction { func governingTokenTX() *transaction.Transaction {
admin, _ := util.Uint160FromScript([]byte{byte(vm.PUSHT)}) admin := hash.Hash160([]byte{byte(vm.PUSHT)})
registerTX := &transaction.RegisterTX{ registerTX := &transaction.RegisterTX{
AssetType: transaction.GoverningToken, AssetType: transaction.GoverningToken,
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]", Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁股\"},{\"lang\":\"en\",\"name\":\"AntShare\"}]",
Amount: util.NewFixed8(100000000), Amount: util.Fixed8FromInt64(100000000),
Precision: 0, Precision: 0,
Owner: &crypto.PublicKey{}, Owner: &crypto.PublicKey{},
Admin: admin, Admin: admin,
@ -120,7 +118,7 @@ func governingTokenTX() *transaction.Transaction {
} }
func utilityTokenTX() *transaction.Transaction { func utilityTokenTX() *transaction.Transaction {
admin, _ := util.Uint160FromScript([]byte{byte(vm.PUSHF)}) admin := hash.Hash160([]byte{byte(vm.PUSHF)})
registerTX := &transaction.RegisterTX{ registerTX := &transaction.RegisterTX{
AssetType: transaction.UtilityToken, AssetType: transaction.UtilityToken,
Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]", Name: "[{\"lang\":\"zh-CN\",\"name\":\"小蚁币\"},{\"lang\":\"en\",\"name\":\"AntCoin\"}]",
@ -162,7 +160,7 @@ func getNextConsensusAddress(validators []*crypto.PublicKey) (val util.Uint160,
if err != nil { if err != nil {
return val, err return val, err
} }
return util.Uint160FromScript(raw) return hash.Hash160(raw), nil
} }
func calculateUtilityAmount() util.Fixed8 { func calculateUtilityAmount() util.Fixed8 {
@ -170,7 +168,7 @@ func calculateUtilityAmount() util.Fixed8 {
for i := 0; i < len(genAmount); i++ { for i := 0; i < len(genAmount); i++ {
sum += genAmount[i] sum += genAmount[i]
} }
return util.NewFixed8(int64(sum * decrementInterval)) return util.Fixed8FromInt64(int64(sum * decrementInterval))
} }
// headerSliceReverse reverses the given slice of *Header. // headerSliceReverse reverses the given slice of *Header.

View file

@ -20,7 +20,7 @@ func TestGenesisBlockMainNet(t *testing.T) {
} }
expect := "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf" expect := "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
assert.Equal(t, expect, block.Hash().String()) assert.Equal(t, expect, block.Hash().ReverseString())
} }
func TestGetConsensusAddressMainNet(t *testing.T) { func TestGetConsensusAddressMainNet(t *testing.T) {
@ -51,11 +51,11 @@ func TestGetConsensusAddressMainNet(t *testing.T) {
func TestUtilityTokenTX(t *testing.T) { func TestUtilityTokenTX(t *testing.T) {
expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7" expect := "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"
tx := utilityTokenTX() tx := utilityTokenTX()
assert.Equal(t, expect, tx.Hash().String()) assert.Equal(t, expect, tx.Hash().ReverseString())
} }
func TestGoverningTokenTX(t *testing.T) { func TestGoverningTokenTX(t *testing.T) {
expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b" expect := "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b"
tx := governingTokenTX() tx := governingTokenTX()
assert.Equal(t, expect, tx.Hash().String()) assert.Equal(t, expect, tx.Hash().ReverseString())
} }

View file

@ -2,10 +2,10 @@ package crypto
import ( import (
"bytes" "bytes"
"crypto/sha256"
"fmt" "fmt"
"math/big" "math/big"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
@ -99,19 +99,7 @@ func Base58CheckDecode(s string) (b []byte, err error) {
return nil, errors.New("invalid base-58 check string: missing checksum.") return nil, errors.New("invalid base-58 check string: missing checksum.")
} }
sha := sha256.New() if !bytes.Equal(hash.Checksum(b[:len(b)-4]), b[len(b)-4:]) {
if _, err = sha.Write(b[:len(b)-4]); err != nil {
return nil, err
}
hash := sha.Sum(nil)
sha.Reset()
if _, err = sha.Write(hash); err != nil {
return nil, err
}
hash = sha.Sum(nil)
if !bytes.Equal(hash[0:4], b[len(b)-4:]) {
return nil, errors.New("invalid base-58 check string: invalid checksum.") return nil, errors.New("invalid base-58 check string: invalid checksum.")
} }
@ -123,15 +111,7 @@ func Base58CheckDecode(s string) (b []byte, err error) {
// Base58checkEncode encodes b into a base-58 check encoded string. // Base58checkEncode encodes b into a base-58 check encoded string.
func Base58CheckEncode(b []byte) string { func Base58CheckEncode(b []byte) string {
sha := sha256.New() b = append(b, hash.Checksum(b)...)
sha.Write(b)
hash := sha.Sum(nil)
sha.Reset()
sha.Write(hash)
hash = sha.Sum(nil)
b = append(b, hash[0:4]...)
return Base58Encode(b) return Base58Encode(b)
} }

View file

@ -1,4 +1,4 @@
package base58 package crypto
import ( import (
"encoding/hex" "encoding/hex"
@ -7,10 +7,10 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestDecode(t *testing.T) { func TestBase58Decode(t *testing.T) {
input := "1F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX" input := "1F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX"
data, err := Decode(input) data, err := Base58Decode(input)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -19,12 +19,12 @@ func TestDecode(t *testing.T) {
actual := hex.EncodeToString(data) actual := hex.EncodeToString(data)
assert.Equal(t, expected, actual) assert.Equal(t, expected, actual)
} }
func TestEncode(t *testing.T) { func TestBase58Encode(t *testing.T) {
input := "0099bc78ba577a95a11f1a344d4d2ae55f2f857b989ea5e5e2" input := "0099bc78ba577a95a11f1a344d4d2ae55f2f857b989ea5e5e2"
inputBytes, _ := hex.DecodeString(input) inputBytes, _ := hex.DecodeString(input)
data := Encode(inputBytes) data := Base58Encode(inputBytes)
expected := "F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX" // Removed the 1 as it is not checkEncoding expected := "F1tAaz5x1HUXrCNLbtMDqcw6o5GNn4xqX" // Removed the 1 as it is not checkEncoding
actual := data actual := data

54
pkg/crypto/hash/hash.go Executable file
View file

@ -0,0 +1,54 @@
package hash
import (
"crypto/sha256"
"github.com/CityOfZion/neo-go/pkg/util"
"golang.org/x/crypto/ripemd160"
)
// Sha256 hashes the incoming byte slice
// using the sha256 algorithm
func Sha256(data []byte) util.Uint256 {
hash := sha256.Sum256(data)
return hash
}
// DoubleSha256 performs sha256 twice on the given data
func DoubleSha256(data []byte) util.Uint256 {
var hash util.Uint256
h1 := Sha256(data)
hash = Sha256(h1.Bytes())
return hash
}
// RipeMD160 performs the RIPEMD160 hash algorithm
// on the given data
func RipeMD160(data []byte) util.Uint160 {
var hash util.Uint160
hasher := ripemd160.New()
_, _ = hasher.Write(data)
hash, _ = util.Uint160DecodeBytes(hasher.Sum(nil))
return hash
}
// Hash160 performs sha256 and then ripemd160
// on the given data
func Hash160(data []byte) util.Uint160 {
var hash util.Uint160
h1 := Sha256(data)
h2 := RipeMD160(h1.Bytes())
hash, _ = util.Uint160DecodeBytes(h2.Bytes())
return hash
}
// Checksum returns the checksum for a given piece of data
// using sha256 twice as the hash algorithm
func Checksum(data []byte) []byte {
hash := DoubleSha256(data)
return hash[:4]
}

View file

@ -9,27 +9,20 @@ import (
func TestSha256(t *testing.T) { func TestSha256(t *testing.T) {
input := []byte("hello") input := []byte("hello")
data, err := Sha256(input) data := Sha256(input)
if err != nil {
t.Fatal(err)
}
expected := "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824" expected := "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
actual := hex.EncodeToString(data.Bytes()) // MARK: In the DecodeBytes function, there is a bytes reverse, not sure why? actual := hex.EncodeToString(data.Bytes())
assert.Equal(t, expected, actual) assert.Equal(t, expected, actual)
} }
func TestHashDoubleSha256(t *testing.T) { func TestHashDoubleSha256(t *testing.T) {
input := []byte("hello") input := []byte("hello")
data, err := DoubleSha256(input) data := DoubleSha256(input)
if err != nil { firstSha := Sha256(input)
t.Fatal(err) doubleSha := Sha256(firstSha.Bytes())
}
firstSha, _ := Sha256(input)
doubleSha, _ := Sha256(firstSha.Bytes())
expected := hex.EncodeToString(doubleSha.Bytes()) expected := hex.EncodeToString(doubleSha.Bytes())
actual := hex.EncodeToString(data.Bytes()) actual := hex.EncodeToString(data.Bytes())
@ -38,11 +31,8 @@ func TestHashDoubleSha256(t *testing.T) {
func TestHashRipeMD160(t *testing.T) { func TestHashRipeMD160(t *testing.T) {
input := []byte("hello") input := []byte("hello")
data, err := RipeMD160(input) data := RipeMD160(input)
if err != nil {
t.Fatal(err)
}
expected := "108f07b8382412612c048d07d13f814118445acd" expected := "108f07b8382412612c048d07d13f814118445acd"
actual := hex.EncodeToString(data.Bytes()) actual := hex.EncodeToString(data.Bytes())
assert.Equal(t, expected, actual) assert.Equal(t, expected, actual)
@ -51,11 +41,8 @@ func TestHashRipeMD160(t *testing.T) {
func TestHash160(t *testing.T) { func TestHash160(t *testing.T) {
input := "02cccafb41b220cab63fd77108d2d1ebcffa32be26da29a04dca4996afce5f75db" input := "02cccafb41b220cab63fd77108d2d1ebcffa32be26da29a04dca4996afce5f75db"
publicKeyBytes, _ := hex.DecodeString(input) publicKeyBytes, _ := hex.DecodeString(input)
data, err := Hash160(publicKeyBytes) data := Hash160(publicKeyBytes)
if err != nil {
t.Fatal(err)
}
expected := "c8e2b685cc70ec96743b55beb9449782f8f775d8" expected := "c8e2b685cc70ec96743b55beb9449782f8f775d8"
actual := hex.EncodeToString(data.Bytes()) actual := hex.EncodeToString(data.Bytes())
assert.Equal(t, expected, actual) assert.Equal(t, expected, actual)

View file

@ -1,9 +1,9 @@
package crypto package crypto
import ( import (
"crypto/sha256"
"errors" "errors"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
) )
@ -67,7 +67,7 @@ func buildMerkleTree(leaves []*MerkleTreeNode) (*MerkleTreeNode, error) {
b1 := parents[i].leftChild.hash.Bytes() b1 := parents[i].leftChild.hash.Bytes()
b2 := parents[i].rightChild.hash.Bytes() b2 := parents[i].rightChild.hash.Bytes()
b1 = append(b1, b2...) b1 = append(b1, b2...)
parents[i].hash = hash256(b1) parents[i].hash = hash.DoubleSha256(b1)
} }
return buildMerkleTree(parents) return buildMerkleTree(parents)
@ -90,10 +90,3 @@ func (n *MerkleTreeNode) IsLeaf() bool {
func (n *MerkleTreeNode) IsRoot() bool { func (n *MerkleTreeNode) IsRoot() bool {
return n.parent == nil return n.parent == nil
} }
func hash256(b []byte) util.Uint256 {
var hash util.Uint256
hash = sha256.Sum256(b)
hash = sha256.Sum256(hash.Bytes())
return hash
}

View file

@ -17,7 +17,7 @@ func TestComputeMerkleTree(t *testing.T) {
hashes := make([]util.Uint256, len(rawHashes)) hashes := make([]util.Uint256, len(rawHashes))
for i, str := range rawHashes { for i, str := range rawHashes {
hash, _ := util.Uint256DecodeString(str) hash, _ := util.Uint256DecodeReverseString(str)
hashes[i] = hash hashes[i] = hash
} }
@ -25,5 +25,5 @@ func TestComputeMerkleTree(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
assert.Equal(t, "803ff4abe3ea6533bcc0be574efa02f83ae8fdc651c879056b0d9be336c01bf4", merkle.Root().String()) assert.Equal(t, "803ff4abe3ea6533bcc0be574efa02f83ae8fdc651c879056b0d9be336c01bf4", merkle.Root().ReverseString())
} }

View file

@ -3,15 +3,14 @@ package crypto
import ( import (
"bytes" "bytes"
"crypto/ecdsa" "crypto/ecdsa"
"crypto/sha256"
"crypto/x509" "crypto/x509"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"io" "io"
"math/big" "math/big"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/crypto/ripemd160"
) )
// PublicKeys is a list of public keys. // PublicKeys is a list of public keys.
@ -172,16 +171,9 @@ func (p *PublicKey) Signature() ([]byte, error) {
b = append([]byte{0x21}, b...) b = append([]byte{0x21}, b...)
b = append(b, 0xAC) b = append(b, 0xAC)
sha := sha256.New() sig := hash.Hash160(b)
sha.Write(b)
hash := sha.Sum(nil)
ripemd := ripemd160.New() return sig.Bytes(), nil
ripemd.Reset()
ripemd.Write(hash)
hash = ripemd.Sum(nil)
return hash, nil
} }
func (p *PublicKey) Address() (string, error) { func (p *PublicKey) Address() (string, error) {
@ -195,15 +187,8 @@ func (p *PublicKey) Address() (string, error) {
b = append([]byte{0x17}, b...) b = append([]byte{0x17}, b...)
sha := sha256.New() csum := hash.Checksum(b)
sha.Write(b) b = append(b, csum...)
hash := sha.Sum(nil)
sha.Reset()
sha.Write(hash)
hash = sha.Sum(nil)
b = append(b, hash[0:4]...)
address := Base58Encode(b) address := Base58Encode(b)
return address, nil return address, nil

View file

@ -1,6 +1,7 @@
package network package network
import ( import (
"math/rand"
"testing" "testing"
"time" "time"
@ -149,7 +150,7 @@ func newTestServer() *Server {
chain: testChain{}, chain: testChain{},
transport: localTransport{}, transport: localTransport{},
discovery: testDiscovery{}, discovery: testDiscovery{},
id: util.RandUint32(1000000, 9999999), id: rand.Uint32(),
quit: make(chan struct{}), quit: make(chan struct{}),
register: make(chan Peer), register: make(chan Peer),
unregister: make(chan peerDrop), unregister: make(chan peerDrop),

View file

@ -2,7 +2,6 @@ package network
import ( import (
"bytes" "bytes"
"crypto/sha256"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
@ -11,6 +10,7 @@ import (
"github.com/CityOfZion/neo-go/config" "github.com/CityOfZion/neo-go/config"
"github.com/CityOfZion/neo-go/pkg/core" "github.com/CityOfZion/neo-go/pkg/core"
"github.com/CityOfZion/neo-go/pkg/core/transaction" "github.com/CityOfZion/neo-go/pkg/core/transaction"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/network/payload" "github.com/CityOfZion/neo-go/pkg/network/payload"
) )
@ -81,9 +81,9 @@ func NewMessage(magic config.NetMode, cmd CommandType, p payload.Payload) *Messa
panic(err) panic(err)
} }
size = uint32(buf.Len()) size = uint32(buf.Len())
checksum = sumSHA256(sumSHA256(buf.Bytes())) checksum = hash.Checksum(buf.Bytes())
} else { } else {
checksum = sumSHA256(sumSHA256([]byte{})) checksum = hash.Checksum([]byte{})
} }
return &Message{ return &Message{
@ -269,14 +269,8 @@ func cmdByteArrayToString(cmd [cmdSize]byte) string {
return string(buf) return string(buf)
} }
func sumSHA256(b []byte) []byte {
h := sha256.New()
h.Write(b)
return h.Sum(nil)
}
func compareChecksum(have uint32, b []byte) bool { func compareChecksum(have uint32, b []byte) bool {
sum := sumSHA256(sumSHA256(b))[:4] sum := hash.Checksum(b)
want := binary.LittleEndian.Uint32(sum) want := binary.LittleEndian.Uint32(sum)
return have == want return have == want
} }

View file

@ -2,19 +2,19 @@ package payload
import ( import (
"bytes" "bytes"
"crypto/sha256"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestGetBlockEncodeDecode(t *testing.T) { func TestGetBlockEncodeDecode(t *testing.T) {
start := []util.Uint256{ start := []util.Uint256{
sha256.Sum256([]byte("a")), hash.Sha256([]byte("a")),
sha256.Sum256([]byte("b")), hash.Sha256([]byte("b")),
sha256.Sum256([]byte("c")), hash.Sha256([]byte("c")),
sha256.Sum256([]byte("d")), hash.Sha256([]byte("d")),
} }
p := NewGetBlocks(start, util.Uint256{}) p := NewGetBlocks(start, util.Uint256{})
@ -34,12 +34,12 @@ func TestGetBlockEncodeDecode(t *testing.T) {
func TestGetBlockEncodeDecodeWithHashStop(t *testing.T) { func TestGetBlockEncodeDecodeWithHashStop(t *testing.T) {
var ( var (
start = []util.Uint256{ start = []util.Uint256{
sha256.Sum256([]byte("a")), hash.Sha256([]byte("a")),
sha256.Sum256([]byte("b")), hash.Sha256([]byte("b")),
sha256.Sum256([]byte("c")), hash.Sha256([]byte("c")),
sha256.Sum256([]byte("d")), hash.Sha256([]byte("d")),
} }
stop = sha256.Sum256([]byte("e")) stop = hash.Sha256([]byte("e"))
) )
p := NewGetBlocks(start, stop) p := NewGetBlocks(start, stop)
buf := new(bytes.Buffer) buf := new(bytes.Buffer)

View file

@ -2,17 +2,17 @@ package payload
import ( import (
"bytes" "bytes"
"crypto/sha256"
"reflect" "reflect"
"testing" "testing"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
. "github.com/CityOfZion/neo-go/pkg/util" . "github.com/CityOfZion/neo-go/pkg/util"
) )
func TestInventoryEncodeDecode(t *testing.T) { func TestInventoryEncodeDecode(t *testing.T) {
hashes := []Uint256{ hashes := []Uint256{
sha256.Sum256([]byte("a")), hash.Sha256([]byte("a")),
sha256.Sum256([]byte("b")), hash.Sha256([]byte("b")),
} }
inv := NewInventory(BlockType, hashes) inv := NewInventory(BlockType, hashes)

View file

@ -3,6 +3,7 @@ package network
import ( import (
"errors" "errors"
"fmt" "fmt"
"math/rand"
"sync" "sync"
"time" "time"
@ -61,7 +62,7 @@ func NewServer(config ServerConfig, chain core.Blockchainer) *Server {
s := &Server{ s := &Server{
ServerConfig: config, ServerConfig: config,
chain: chain, chain: chain,
id: util.RandUint32(1000000, 9999999), id: rand.Uint32(),
quit: make(chan struct{}), quit: make(chan struct{}),
register: make(chan Peer), register: make(chan Peer),
unregister: make(chan peerDrop), unregister: make(chan peerDrop),
@ -349,3 +350,7 @@ func (s *Server) RelayDirectly(p Peer, inv *payload.Inventory) {
p.WriteMsg(NewMessage(s.Net, CMDInv, inv)) p.WriteMsg(NewMessage(s.Net, CMDInv, inv))
} }
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}

View file

@ -57,7 +57,7 @@ func (s NeoScanServer) CalculateInputs(address string, assetIdUint util.Uint256,
selected = util.Fixed8(0) selected = util.Fixed8(0)
us []*Unspent us []*Unspent
assetUnspent Unspent assetUnspent Unspent
assetId = GlobalAssets[assetIdUint.String()] assetId = GlobalAssets[assetIdUint.ReverseString()]
) )
if us, err = s.GetBalance(address); err != nil { if us, err = s.GetBalance(address); err != nil {
return nil, util.Fixed8(0), errs.Wrapf(err, "Cannot get balance for address %v", address) return nil, util.Fixed8(0), errs.Wrapf(err, "Cannot get balance for address %v", address)

View file

@ -139,7 +139,7 @@ func (c *Client) SendToAddress(asset util.Uint256, address string, amount util.F
response.ID = resp.ID response.ID = resp.ID
response.JSONRPC = resp.JSONRPC response.JSONRPC = resp.JSONRPC
response.Result = &TxResponse{ response.Result = &TxResponse{
TxID: rawTx.Hash().String(), TxID: rawTx.Hash().ReverseString(),
} }
return response, nil return response, nil
} }

View file

@ -107,7 +107,7 @@ func (s *Server) methodHandler(w http.ResponseWriter, req *Request, reqParams Pa
Methods: Methods:
switch req.Method { switch req.Method {
case "getbestblockhash": case "getbestblockhash":
results = s.chain.CurrentBlockHash().String() results = s.chain.CurrentBlockHash().ReverseString()
case "getblock": case "getblock":
var hash util.Uint256 var hash util.Uint256
@ -120,7 +120,7 @@ Methods:
switch param.Type { switch param.Type {
case "string": case "string":
hash, err = util.Uint256DecodeString(param.StringVal) hash, err = util.Uint256DecodeReverseString(param.StringVal)
if err != nil { if err != nil {
resultsErr = errInvalidParams resultsErr = errInvalidParams
break Methods break Methods
@ -204,7 +204,7 @@ Methods:
break Methods break Methods
} }
paramAssetID, err := util.Uint256DecodeString(param.StringVal) paramAssetID, err := util.Uint256DecodeReverseString(param.StringVal)
if err != nil { if err != nil {
resultsErr = errInvalidParams resultsErr = errInvalidParams
break break
@ -253,7 +253,7 @@ func (s *Server) getrawtransaction(reqParams Params) (interface{}, error) {
param0, err := reqParams.ValueWithType(0, "string") param0, err := reqParams.ValueWithType(0, "string")
if err != nil { if err != nil {
resultsErr = err resultsErr = err
} else if txHash, err := util.Uint256DecodeString(param0.StringVal); err != nil { } else if txHash, err := util.Uint256DecodeReverseString(param0.StringVal); err != nil {
resultsErr = errInvalidParams resultsErr = errInvalidParams
} else if tx, height, err := s.chain.GetTransaction(txHash); err != nil { } else if tx, height, err := s.chain.GetTransaction(txHash); err != nil {
err = errors.Wrapf(err, "Invalid transaction hash: %s", txHash) err = errors.Wrapf(err, "Invalid transaction hash: %s", txHash)

View file

@ -165,7 +165,7 @@ var testRpcCases = []tc{
{ {
rpcCall: `{ "jsonrpc": "2.0", "id": 1, "method": "getaccountstate", "params": ["AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"] }`, rpcCall: `{ "jsonrpc": "2.0", "id": 1, "method": "getaccountstate", "params": ["AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y"] }`,
method: "getaccountstate_1", method: "getaccountstate_1",
expectedResult: `{"jsonrpc":"2.0","result":{"version":0,"script_hash":"0xe9eed8dc39332032dc22e5d6e86332c50327ba23","frozen":false,"votes":[],"balances":[{"asset":"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7","value":"72099.99960000"},{"asset":"0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b","value":"99989900"}]},"id":1}`, expectedResult: `{"jsonrpc":"2.0","result":{"version":0,"script_hash":"0xe9eed8dc39332032dc22e5d6e86332c50327ba23","frozen":false,"votes":[],"balances":[{"asset":"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7","value":"72099.9996"},{"asset":"0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b","value":"99989900"}]},"id":1}`,
}, },
// Bad case, invalid address // Bad case, invalid address

View file

@ -214,7 +214,7 @@ func (p StackParam) TryParse(dest interface{}) error {
*dest = data *dest = data
return nil return nil
case *util.Uint256: case *util.Uint256:
if *dest, err = util.Uint256DecodeBytes(data); err != nil { if *dest, err = util.Uint256DecodeReverseBytes(data); err != nil {
return err return err
} }
return nil return nil

View file

@ -90,7 +90,7 @@ func TestStackParam_UnmarshalJSON(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("error while unmarhsalling: %v", err) t.Errorf("error while unmarhsalling: %v", err)
} }
h256, err := util.Uint256DecodeString("f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d") h256, err := util.Uint256DecodeReverseString("f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d")
if err != nil { if err != nil {
t.Errorf("unmarshal error: %v", err) t.Errorf("unmarshal error: %v", err)
} }
@ -149,7 +149,7 @@ func TestStackParam_TryParse(t *testing.T) {
Value: data, Value: data,
} }
) )
expectedUint256, err = util.Uint256DecodeString(hash256) expectedUint256, err = util.Uint256DecodeReverseString(hash256)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -5,7 +5,16 @@ import (
"testing" "testing"
) )
func TestArrayReverse(t *testing.T) { func TestArrayEvenReverse(t *testing.T) {
arr := []byte{0x01, 0x02, 0x03, 0x04}
have := ArrayReverse(arr)
want := []byte{0x04, 0x03, 0x02, 0x01}
if !bytes.Equal(have, want) {
t.Fatalf("expected %v got %v", want, have)
}
}
func TestArrayOddReverse(t *testing.T) {
arr := []byte{0x01, 0x02, 0x03, 0x04, 0x05} arr := []byte{0x01, 0x02, 0x03, 0x04, 0x05}
have := ArrayReverse(arr) have := ArrayReverse(arr)
want := []byte{0x05, 0x04, 0x03, 0x02, 0x01} want := []byte{0x05, 0x04, 0x03, 0x02, 0x01}

View file

@ -34,29 +34,34 @@ func (f Fixed8) String() string {
for i := len(str); i < 8; i++ { for i := len(str); i < 8; i++ {
buf.WriteRune('0') buf.WriteRune('0')
} }
buf.WriteString(str) buf.WriteString(strings.TrimRight(str, "0"))
} }
return buf.String() return buf.String()
} }
// Value returns the original value representing the Fixed8. // FloatValue returns the original value representing Fixed8 as float64.
func (f Fixed8) Value() int64 { func (f Fixed8) FloatValue() float64 {
return float64(f) / decimals
}
// Int64Value returns the original value representing Fixed8 as int64.
func (f Fixed8) Int64Value() int64 {
return int64(f) / decimals return int64(f) / decimals
} }
// NewFixed8 returns a new Fixed8 type multiplied by decimals. // Fixed8FromInt64 returns a new Fixed8 type multiplied by decimals.
func NewFixed8(val int64) Fixed8 { func Fixed8FromInt64(val int64) Fixed8 {
return Fixed8(decimals * val) return Fixed8(decimals * val)
} }
// NewFixed8FromFloat returns a new Fixed8 type multiplied by decimals. // Fixed8FromFloat returns a new Fixed8 type multiplied by decimals.
func NewFixed8FromFloat(val float64) Fixed8 { func Fixed8FromFloat(val float64) Fixed8 {
return Fixed8(int64(decimals * val)) return Fixed8(int64(decimals * val))
} }
// Fixed8DecodeString parses s which must be a fixed point number // Fixed8FromString parses s which must be a fixed point number
// with precision up to 10^-8 // with precision up to 10^-8
func Fixed8DecodeString(s string) (Fixed8, error) { func Fixed8FromString(s string) (Fixed8, error) {
parts := strings.SplitN(s, ".", 2) parts := strings.SplitN(s, ".", 2)
ip, err := strconv.ParseInt(parts[0], 10, 64) ip, err := strconv.ParseInt(parts[0], 10, 64)
if err != nil { if err != nil {
@ -82,7 +87,7 @@ func Fixed8DecodeString(s string) (Fixed8, error) {
func (f *Fixed8) UnmarshalJSON(data []byte) error { func (f *Fixed8) UnmarshalJSON(data []byte) error {
var s string var s string
if err := json.Unmarshal(data, &s); err == nil { if err := json.Unmarshal(data, &s); err == nil {
p, err := Fixed8DecodeString(s) p, err := Fixed8FromString(s)
if err != nil { if err != nil {
return err return err
} }
@ -111,37 +116,37 @@ func (f Fixed8) MarshalJSON() ([]byte, error) {
// Satoshi defines the value of a 'Satoshi'. // Satoshi defines the value of a 'Satoshi'.
func Satoshi() Fixed8 { func Satoshi() Fixed8 {
return NewFixed8(1) return Fixed8(1)
} }
// Div implements Fixd8 division operator. // Div implements Fixd8 division operator.
func (f Fixed8) Div(i int64) Fixed8 { func (f Fixed8) Div(i int64) Fixed8 {
return NewFixed8(f.Value() / i) return f / Fixed8FromInt64(i)
} }
// Add implements Fixd8 addition operator. // Add implements Fixd8 addition operator.
func (f Fixed8) Add(g Fixed8) Fixed8 { func (f Fixed8) Add(g Fixed8) Fixed8 {
return NewFixed8(f.Value() + g.Value()) return f + g
} }
// Sub implements Fixd8 subtraction operator. // Sub implements Fixd8 subtraction operator.
func (f Fixed8) Sub(g Fixed8) Fixed8 { func (f Fixed8) Sub(g Fixed8) Fixed8 {
return NewFixed8(f.Value() - g.Value()) return f - g
} }
// LessThan implements Fixd8 < operator. // LessThan implements Fixd8 < operator.
func (f Fixed8) LessThan(g Fixed8) bool { func (f Fixed8) LessThan(g Fixed8) bool {
return f.Value() < g.Value() return f < g
} }
// GreaterThan implements Fixd8 < operator. // GreaterThan implements Fixd8 < operator.
func (f Fixed8) GreaterThan(g Fixed8) bool { func (f Fixed8) GreaterThan(g Fixed8) bool {
return f.Value() > g.Value() return f > g
} }
// Equal implements Fixd8 == operator. // Equal implements Fixd8 == operator.
func (f Fixed8) Equal(g Fixed8) bool { func (f Fixed8) Equal(g Fixed8) bool {
return f.Value() == g.Value() return f == g
} }
// CompareTo returns the difference between the f and g. // CompareTo returns the difference between the f and g.
@ -149,5 +154,5 @@ func (f Fixed8) Equal(g Fixed8) bool {
// difference = 0 implies f = g. // difference = 0 implies f = g.
// difference > 0 implies f > g. // difference > 0 implies f > g.
func (f Fixed8) CompareTo(g Fixed8) int { func (f Fixed8) CompareTo(g Fixed8) int {
return int(f.Value() - g.Value()) return int(f - g)
} }

View file

@ -8,37 +8,69 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestNewFixed8(t *testing.T) { func TestFixed8FromInt64(t *testing.T) {
values := []int64{9000, 100000000, 5, 10945} values := []int64{9000, 100000000, 5, 10945, -42}
for _, val := range values { for _, val := range values {
assert.Equal(t, Fixed8(val*decimals), NewFixed8(val)) assert.Equal(t, Fixed8(val*decimals), Fixed8FromInt64(val))
assert.Equal(t, val, NewFixed8(val).Value()) assert.Equal(t, val, Fixed8FromInt64(val).Int64Value())
} }
} }
func TestFixed8DecodeString(t *testing.T) { func TestFixed8Add(t *testing.T) {
// Fixed8DecodeString works correctly with integers a := Fixed8FromInt64(1)
ivalues := []string{"9000", "100000000", "5", "10945"} b := Fixed8FromInt64(2)
c := a.Add(b)
expected := int64(3)
assert.Equal(t, strconv.FormatInt(expected, 10), c.String())
}
func TestFixed8Sub(t *testing.T) {
a := Fixed8FromInt64(42)
b := Fixed8FromInt64(34)
c := a.Sub(b)
assert.Equal(t, int64(8), c.Int64Value())
}
func TestFixed8FromFloat(t *testing.T) {
inputs := []float64{12.98, 23.87654333, 100.654322, 456789.12345665, -3.14159265}
for _, val := range inputs {
assert.Equal(t, Fixed8(val*decimals), Fixed8FromFloat(val))
assert.Equal(t, val, Fixed8FromFloat(val).FloatValue())
}
}
func TestFixed8FromString(t *testing.T) {
// Fixed8FromString works correctly with integers
ivalues := []string{"9000", "100000000", "5", "10945", "20.45", "0.00000001", "-42"}
for _, val := range ivalues { for _, val := range ivalues {
n, err := Fixed8DecodeString(val) n, err := Fixed8FromString(val)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, val, n.String()) assert.Equal(t, val, n.String())
} }
// Fixed8DecodeString parses number with maximal precision // Fixed8FromString parses number with maximal precision
val := "123456789.12345678" val := "123456789.12345678"
n, err := Fixed8DecodeString(val) n, err := Fixed8FromString(val)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, Fixed8(12345678912345678), n) assert.Equal(t, Fixed8(12345678912345678), n)
// Fixed8DecodeString parses number with non-maximal precision // Fixed8FromString parses number with non-maximal precision
val = "901.2341" val = "901.2341"
n, err = Fixed8DecodeString(val) n, err = Fixed8FromString(val)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, Fixed8(90123410000), n) assert.Equal(t, Fixed8(90123410000), n)
} }
func TestSatoshi(t *testing.T) {
satoshif8 := Satoshi()
assert.Equal(t, "0.00000001", satoshif8.String())
}
func TestFixed8UnmarshalJSON(t *testing.T) { func TestFixed8UnmarshalJSON(t *testing.T) {
var testCases = []float64{ var testCases = []float64{
123.45, 123.45,
@ -47,7 +79,7 @@ func TestFixed8UnmarshalJSON(t *testing.T) {
for _, fl := range testCases { for _, fl := range testCases {
str := strconv.FormatFloat(fl, 'g', -1, 64) str := strconv.FormatFloat(fl, 'g', -1, 64)
expected, _ := Fixed8DecodeString(str) expected, _ := Fixed8FromString(str)
// UnmarshalJSON should decode floats // UnmarshalJSON should decode floats
var u1 Fixed8 var u1 Fixed8

View file

@ -1,16 +0,0 @@
package util
import (
"math/rand"
"time"
)
// RandUint32 return a random number between min and max.
func RandUint32(min, max int) uint32 {
n := min + rand.Intn(max-min)
return uint32(n)
}
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}

View file

@ -1,45 +0,0 @@
package util
import (
"crypto/sha256"
"math/rand"
"time"
"golang.org/x/crypto/ripemd160"
)
// RandomString returns a random string with the n as its length.
func RandomString(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = byte(RandomInt(65, 90))
}
return string(b)
}
// RandomInt returns a random integer between min and max.
func RandomInt(min, max int) int {
return min + rand.Intn(max-min)
}
// RandomUint256 returns a random Uint256.
func RandomUint256() Uint256 {
str := RandomString(20)
h := sha256.Sum256([]byte(str))
return Uint256(h)
}
// RandomUint160 returns a random Uint160.
func RandomUint160() Uint160 {
str := RandomString(20)
ripemd := ripemd160.New()
ripemd.Write([]byte(str))
h := ripemd.Sum(nil)
v, _ := Uint160DecodeBytes(h)
return v
}
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}

View file

@ -1,13 +1,10 @@
package util package util
import ( import (
"crypto/sha256"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings" "strings"
"golang.org/x/crypto/ripemd160"
) )
const uint160Size = 20 const uint160Size = 20
@ -37,17 +34,6 @@ func Uint160DecodeBytes(b []byte) (u Uint160, err error) {
return return
} }
// Uint160FromScript returns a Uint160 type from a raw script.
func Uint160FromScript(script []byte) (u Uint160, err error) {
sha := sha256.New()
sha.Write(script)
b := sha.Sum(nil)
ripemd := ripemd160.New()
ripemd.Write(b)
b = ripemd.Sum(nil)
return Uint160DecodeBytes(b)
}
// Bytes returns the byte slice representation of u. // Bytes returns the byte slice representation of u.
func (u Uint160) Bytes() []byte { func (u Uint160) Bytes() []byte {
return u[:] return u[:]
@ -63,6 +49,11 @@ func (u Uint160) String() string {
return hex.EncodeToString(u.Bytes()) return hex.EncodeToString(u.Bytes())
} }
// ReverseString is the same as String, but returnes an inversed representation.
func (u Uint160) ReverseString() string {
return hex.EncodeToString(u.BytesReverse())
}
// Equals returns true if both Uint256 values are the same. // Equals returns true if both Uint256 values are the same.
func (u Uint160) Equals(other Uint160) bool { func (u Uint160) Equals(other Uint160) bool {
return u == other return u == other

View file

@ -75,3 +75,14 @@ func TestUInt160Equals(t *testing.T) {
t.Fatalf("%s and %s must be equal", ua, ua) t.Fatalf("%s and %s must be equal", ua, ua)
} }
} }
func TestUInt160String(t *testing.T) {
hexStr := "b28427088a3729b2536d10122960394e8be6721f"
hexRevStr := "1f72e68b4e39602912106d53b229378a082784b2"
val, err := Uint160DecodeString(hexStr)
assert.Nil(t, err)
assert.Equal(t, hexStr, val.String())
assert.Equal(t, hexRevStr, val.ReverseString())
}

View file

@ -13,8 +13,8 @@ const uint256Size = 32
// Uint256 is a 32 byte long unsigned integer. // Uint256 is a 32 byte long unsigned integer.
type Uint256 [uint256Size]uint8 type Uint256 [uint256Size]uint8
// Uint256DecodeString attempts to decode the given string into an Uint256. // Uint256DecodeReverseString attempts to decode the given string (in LE representation) into an Uint256.
func Uint256DecodeString(s string) (u Uint256, err error) { func Uint256DecodeReverseString(s string) (u Uint256, err error) {
if len(s) != uint256Size*2 { if len(s) != uint256Size*2 {
return u, fmt.Errorf("expected string size of %d got %d", uint256Size*2, len(s)) return u, fmt.Errorf("expected string size of %d got %d", uint256Size*2, len(s))
} }
@ -22,12 +22,11 @@ func Uint256DecodeString(s string) (u Uint256, err error) {
if err != nil { if err != nil {
return u, err return u, err
} }
return Uint256DecodeBytes(b) return Uint256DecodeReverseBytes(b)
} }
// Uint256DecodeBytes attempts to decode the given string into an Uint256. // Uint256DecodeBytes attempts to decode the given string (in BE representation) into an Uint256.
func Uint256DecodeBytes(b []byte) (u Uint256, err error) { func Uint256DecodeBytes(b []byte) (u Uint256, err error) {
b = ArrayReverse(b)
if len(b) != uint256Size { if len(b) != uint256Size {
return u, fmt.Errorf("expected []byte of size %d got %d", uint256Size, len(b)) return u, fmt.Errorf("expected []byte of size %d got %d", uint256Size, len(b))
} }
@ -35,11 +34,23 @@ func Uint256DecodeBytes(b []byte) (u Uint256, err error) {
return u, nil return u, nil
} }
// Uint256DecodeReverseBytes attempts to decode the given string (in LE representation) into an Uint256.
func Uint256DecodeReverseBytes(b []byte) (u Uint256, err error) {
b = ArrayReverse(b)
return Uint256DecodeBytes(b)
}
// Bytes returns a byte slice representation of u. // Bytes returns a byte slice representation of u.
func (u Uint256) Bytes() []byte { func (u Uint256) Bytes() []byte {
return u[:] return u[:]
} }
// Reverse reverses the Uint256 object
func (u Uint256) Reverse() Uint256 {
res, _ := Uint256DecodeReverseBytes(u.Bytes())
return res
}
// BytesReverse return a reversed byte representation of u. // BytesReverse return a reversed byte representation of u.
func (u Uint256) BytesReverse() []byte { func (u Uint256) BytesReverse() []byte {
return ArrayReverse(u.Bytes()) return ArrayReverse(u.Bytes())
@ -52,7 +63,12 @@ func (u Uint256) Equals(other Uint256) bool {
// String implements the stringer interface. // String implements the stringer interface.
func (u Uint256) String() string { func (u Uint256) String() string {
return hex.EncodeToString(ArrayReverse(u.Bytes())) return hex.EncodeToString(u.Bytes())
}
// ReverseString produces string representation of Uint256 with LE byte order.
func (u Uint256) ReverseString() string {
return hex.EncodeToString(u.BytesReverse())
} }
// UnmarshalJSON implements the json unmarshaller interface. // UnmarshalJSON implements the json unmarshaller interface.
@ -62,7 +78,7 @@ func (u *Uint256) UnmarshalJSON(data []byte) (err error) {
return err return err
} }
js = strings.TrimPrefix(js, "0x") js = strings.TrimPrefix(js, "0x")
*u, err = Uint256DecodeString(js) *u, err = Uint256DecodeReverseString(js)
return err return err
} }
@ -73,7 +89,7 @@ func (u Uint256) Size() int {
// MarshalJSON implements the json marshaller interface. // MarshalJSON implements the json marshaller interface.
func (u Uint256) MarshalJSON() ([]byte, error) { func (u Uint256) MarshalJSON() ([]byte, error) {
return []byte(`"0x` + u.String() + `"`), nil return []byte(`"0x` + u.ReverseString() + `"`), nil
} }
// CompareTo compares two Uint256 with each other. Possible output: 1, -1, 0 // CompareTo compares two Uint256 with each other. Possible output: 1, -1, 0

View file

@ -9,7 +9,7 @@ import (
func TestUint256UnmarshalJSON(t *testing.T) { func TestUint256UnmarshalJSON(t *testing.T) {
str := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d" str := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
expected, err := Uint256DecodeString(str) expected, err := Uint256DecodeReverseString(str)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -36,11 +36,11 @@ func TestUint256UnmarshalJSON(t *testing.T) {
func TestUint256DecodeString(t *testing.T) { func TestUint256DecodeString(t *testing.T) {
hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d" hexStr := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
val, err := Uint256DecodeString(hexStr) val, err := Uint256DecodeReverseString(hexStr)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
assert.Equal(t, hexStr, val.String()) assert.Equal(t, hexStr, val.ReverseString())
} }
func TestUint256DecodeBytes(t *testing.T) { func TestUint256DecodeBytes(t *testing.T) {
@ -49,22 +49,22 @@ func TestUint256DecodeBytes(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
val, err := Uint256DecodeBytes(b) val, err := Uint256DecodeReverseBytes(b)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
assert.Equal(t, hexStr, val.String()) assert.Equal(t, hexStr, val.ReverseString())
} }
func TestUInt256Equals(t *testing.T) { func TestUInt256Equals(t *testing.T) {
a := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d" a := "f037308fa0ab18155bccfc08485468c112409ea5064595699e98c545f245f32d"
b := "e287c5b29a1b66092be6803c59c765308ac20287e1b4977fd399da5fc8f66ab5" b := "e287c5b29a1b66092be6803c59c765308ac20287e1b4977fd399da5fc8f66ab5"
ua, err := Uint256DecodeString(a) ua, err := Uint256DecodeReverseString(a)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
ub, err := Uint256DecodeString(b) ub, err := Uint256DecodeReverseString(b)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -2,7 +2,6 @@ package vm
import ( import (
"crypto/sha1" "crypto/sha1"
"crypto/sha256"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
@ -11,8 +10,8 @@ import (
"text/tabwriter" "text/tabwriter"
"reflect" "reflect"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"github.com/CityOfZion/neo-go/pkg/util" "github.com/CityOfZion/neo-go/pkg/util"
"golang.org/x/crypto/ripemd160"
) )
// Mode configures behaviour of the VM. // Mode configures behaviour of the VM.
@ -676,27 +675,15 @@ func (v *VM) execute(ctx *Context, op Instruction) {
case SHA256: case SHA256:
b := v.estack.Pop().Bytes() b := v.estack.Pop().Bytes()
sha := sha256.New() v.estack.PushVal(hash.Sha256(b).Bytes())
sha.Write(b)
v.estack.PushVal(sha.Sum(nil))
case HASH160: case HASH160:
b := v.estack.Pop().Bytes() b := v.estack.Pop().Bytes()
sha := sha256.New() v.estack.PushVal(hash.Hash160(b).Bytes())
sha.Write(b)
h := sha.Sum(nil)
ripemd := ripemd160.New()
ripemd.Write(h)
v.estack.PushVal(ripemd.Sum(nil))
case HASH256: case HASH256:
b := v.estack.Pop().Bytes() b := v.estack.Pop().Bytes()
sha := sha256.New() v.estack.PushVal(hash.DoubleSha256(b).Bytes())
sha.Write(b)
h := sha.Sum(nil)
sha.Reset()
sha.Write(h)
v.estack.PushVal(sha.Sum(nil))
case CHECKSIG: case CHECKSIG:
// pubkey := v.estack.Pop().Bytes() // pubkey := v.estack.Pop().Bytes()

View file

@ -2,11 +2,11 @@ package wallet
import ( import (
"bytes" "bytes"
"crypto/sha256"
"errors" "errors"
"fmt" "fmt"
"github.com/CityOfZion/neo-go/pkg/crypto" "github.com/CityOfZion/neo-go/pkg/crypto"
"github.com/CityOfZion/neo-go/pkg/crypto/hash"
"golang.org/x/crypto/scrypt" "golang.org/x/crypto/scrypt"
"golang.org/x/text/unicode/norm" "golang.org/x/text/unicode/norm"
) )
@ -46,7 +46,7 @@ func NEP2Encrypt(priv *PrivateKey, passphrase string) (s string, err error) {
return s, err return s, err
} }
addrHash := hashAddress(address)[0:4] addrHash := hash.Checksum([]byte(address))
// Normalize the passphrase according to the NFC standard. // Normalize the passphrase according to the NFC standard.
phraseNorm := norm.NFC.Bytes([]byte(passphrase)) phraseNorm := norm.NFC.Bytes([]byte(passphrase))
derivedKey, err := scrypt.Key(phraseNorm, addrHash, n, r, p, keyLen) derivedKey, err := scrypt.Key(phraseNorm, addrHash, n, r, p, keyLen)
@ -119,13 +119,13 @@ func NEP2Decrypt(key, passphrase string) (s string, err error) {
return privKey.WIF() return privKey.WIF()
} }
func compareAddressHash(priv *PrivateKey, hash []byte) bool { func compareAddressHash(priv *PrivateKey, inhash []byte) bool {
address, err := priv.Address() address, err := priv.Address()
if err != nil { if err != nil {
return false return false
} }
addrHash := hashAddress(address)[0:4] addrHash := hash.Checksum([]byte(address))
return bytes.Equal(addrHash, hash) return bytes.Equal(addrHash, inhash)
} }
func validateNEP2Format(b []byte) error { func validateNEP2Format(b []byte) error {
@ -154,12 +154,3 @@ func xor(a, b []byte) []byte {
} }
return dst return dst
} }
func hashAddress(addr string) []byte {
sha := sha256.New()
sha.Write([]byte(addr))
hash := sha.Sum(nil)
sha.Reset()
sha.Write(hash)
return sha.Sum(nil)
}