Timeout outgoing connections in 10 seconds, reduce memory allocations, use sync.Pool for storing allocations
This commit is contained in:
parent
cec700beac
commit
7929753c40
|
@ -7,6 +7,7 @@ import (
|
|||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"log"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -53,19 +54,26 @@ func TestSort(t *testing.T) {
|
|||
}
|
||||
|
||||
func BenchmarkCoinbaseDerivation(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
packed := testAddress3.ToPackedAddress()
|
||||
txKey := crypto.PrivateKeyFromScalar(privateKey)
|
||||
for i := 0; i < b.N; i++ {
|
||||
GetEphemeralPublicKey(packed, txKey, uint64(i))
|
||||
}
|
||||
var i atomic.Uint64
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
GetEphemeralPublicKey(packed, txKey, i.Load())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkCoinbaseDerivationInline(b *testing.B) {
|
||||
packed := testAddress3.ToPackedAddress()
|
||||
spendPub, viewPub := packed.SpendPublicKey().AsPoint().Point(), packed.ViewPublicKey().AsPoint().Point()
|
||||
|
||||
p := new(edwards25519.Point)
|
||||
for i := 0; i < b.N; i++ {
|
||||
getEphemeralPublicKeyInline(spendPub, viewPub, privateKey, uint64(i), p)
|
||||
}
|
||||
}
|
||||
var i atomic.Uint64
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
p := new(edwards25519.Point)
|
||||
for pb.Next() {
|
||||
getEphemeralPublicKeyInline(spendPub, viewPub, privateKey, i.Load(), p)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func GetEphemeralPublicKey(a Interface, txKey crypto.PrivateKey, outputIndex uin
|
|||
return GetPublicKeyForSharedData(a, crypto.GetDerivationSharedDataForOutputIndex(txKey.GetDerivationCofactor(a.ViewPublicKey()), outputIndex))
|
||||
}
|
||||
|
||||
func getEphemeralPublicKeyInline(spendPub, viewPub *edwards25519.Point, txKey *edwards25519.Scalar, outputIndex uint64, p *edwards25519.Point) {
|
||||
func getEphemeralPublicKeyInline(spendPub, viewPub *edwards25519.Point, txKey *edwards25519.Scalar, outputIndex uint64, p *edwards25519.Point) {
|
||||
//derivation
|
||||
p.ScalarMult(txKey, viewPub).MultByCofactor(p)
|
||||
|
||||
|
@ -41,7 +41,7 @@ func GetEphemeralPublicKeyAndViewTag(a Interface, txKey crypto.PrivateKey, outpu
|
|||
}
|
||||
|
||||
func GetTxProofV2(a Interface, txId types.Hash, txKey crypto.PrivateKey, message string) string {
|
||||
prefixHash := types.Hash(moneroutil.Keccak256(txId[:], []byte(message)))
|
||||
prefixHash := crypto.Keccak256(txId[:], []byte(message))
|
||||
|
||||
sharedSecret, signature := crypto.GenerateTxProofV2(prefixHash, txKey, a.ViewPublicKey(), nil)
|
||||
|
||||
|
@ -49,7 +49,7 @@ func GetTxProofV2(a Interface, txId types.Hash, txKey crypto.PrivateKey, message
|
|||
}
|
||||
|
||||
func GetTxProofV1(a Interface, txId types.Hash, txKey crypto.PrivateKey, message string) string {
|
||||
prefixHash := types.Hash(moneroutil.Keccak256(txId[:], []byte(message)))
|
||||
prefixHash := crypto.Keccak256(txId[:], []byte(message))
|
||||
|
||||
sharedSecret, signature := crypto.GenerateTxProofV1(prefixHash, txKey, a.ViewPublicKey(), nil)
|
||||
|
||||
|
@ -65,21 +65,21 @@ const (
|
|||
)
|
||||
|
||||
func GetMessageHash(a Interface, message []byte, mode uint8) types.Hash {
|
||||
return types.Hash(moneroutil.Keccak256(
|
||||
return crypto.Keccak256(
|
||||
[]byte("MoneroMessageSignature\x00"),
|
||||
a.SpendPublicKey().AsSlice(),
|
||||
a.ViewPublicKey().AsSlice(),
|
||||
[]byte{mode},
|
||||
binary.AppendUvarint(nil, uint64(len(message))),
|
||||
message,
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
func VerifyMessage(a Interface, message []byte, signature string) SignatureVerifyResult {
|
||||
var hash types.Hash
|
||||
|
||||
if strings.HasPrefix(signature, "SigV1") {
|
||||
hash = types.Hash(moneroutil.Keccak256(message))
|
||||
hash = crypto.Keccak256(message)
|
||||
} else if strings.HasPrefix(signature, "SigV2") {
|
||||
hash = GetMessageHash(a, message, 0)
|
||||
} else {
|
||||
|
|
|
@ -3,12 +3,13 @@ package block
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/client"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/randomx"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/transaction"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"hash"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
@ -197,6 +198,8 @@ func (b *Block) TxTreeHash() (rootHash types.Hash) {
|
|||
} else if count == 2 {
|
||||
rootHash = types.HashFromBytes(keccak(h))
|
||||
} else {
|
||||
hashInstance := crypto.GetKeccak256Hasher()
|
||||
defer crypto.PutKeccak256Hasher(hashInstance)
|
||||
var cnt int
|
||||
|
||||
{
|
||||
|
@ -214,7 +217,7 @@ func (b *Block) TxTreeHash() (rootHash types.Hash) {
|
|||
i := cnt*2 - count
|
||||
j := cnt*2 - count
|
||||
for j < cnt {
|
||||
copy(ints[j*types.HashSize:], keccakl(h[i*types.HashSize:], types.HashSize*2))
|
||||
keccakl(hashInstance, ints[j*types.HashSize:], h[i*types.HashSize:], types.HashSize*2)
|
||||
i += 2
|
||||
j++
|
||||
}
|
||||
|
@ -227,7 +230,7 @@ func (b *Block) TxTreeHash() (rootHash types.Hash) {
|
|||
j := 0
|
||||
|
||||
for j < cnt {
|
||||
copy(ints[j*types.HashSize:], keccakl(ints[i*types.HashSize:], types.HashSize*2))
|
||||
keccakl(hashInstance, ints[j*types.HashSize:], ints[i*types.HashSize:], types.HashSize*2)
|
||||
|
||||
i += 2
|
||||
j++
|
||||
|
@ -235,7 +238,7 @@ func (b *Block) TxTreeHash() (rootHash types.Hash) {
|
|||
}
|
||||
}
|
||||
|
||||
copy(rootHash[:], keccakl(ints, types.HashSize*2))
|
||||
keccakl(hashInstance, rootHash[:], ints, types.HashSize*2)
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -261,15 +264,15 @@ func (b *Block) PowHashWithError() (types.Hash, error) {
|
|||
func (b *Block) Id() types.Hash {
|
||||
//cached by sidechain.Share
|
||||
buf := b.HashingBlob()
|
||||
return types.Hash(moneroutil.Keccak256(binary.AppendUvarint(nil, uint64(len(buf))), buf))
|
||||
return crypto.PooledKeccak256(binary.AppendUvarint(nil, uint64(len(buf))), buf)
|
||||
}
|
||||
|
||||
var hasher = randomx.NewRandomX()
|
||||
|
||||
func keccakl(data []byte, len int) []byte {
|
||||
h := sha3.NewLegacyKeccak256()
|
||||
h.Write(data[:len])
|
||||
return h.Sum(nil)
|
||||
func keccakl(hasher hash.Hash, dst []byte, data []byte, len int) {
|
||||
hasher.Reset()
|
||||
hasher.Write(data[:len])
|
||||
crypto.HashFastSum(hasher, dst)
|
||||
}
|
||||
|
||||
func keccak(data ...[]byte) []byte {
|
||||
|
|
|
@ -2,7 +2,6 @@ package crypto
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
)
|
||||
|
||||
func GetDerivationSharedDataForOutputIndex(derivation PublicKey, outputIndex uint64) PrivateKey {
|
||||
|
@ -14,8 +13,7 @@ func GetDerivationSharedDataForOutputIndex(derivation PublicKey, outputIndex uin
|
|||
func GetDerivationViewTagForOutputIndex(derivation PublicKey, outputIndex uint64) uint8 {
|
||||
var k = derivation.AsBytes()
|
||||
var varIntBuf [binary.MaxVarintLen64]byte
|
||||
h := moneroutil.Keccak256([]byte("view_tag"), k[:], varIntBuf[:binary.PutUvarint(varIntBuf[:], outputIndex)])
|
||||
return h[0]
|
||||
return PooledKeccak256([]byte("view_tag"), k[:], varIntBuf[:binary.PutUvarint(varIntBuf[:], outputIndex)])[0]
|
||||
}
|
||||
|
||||
func GetDerivationSharedDataAndViewTagForOutputIndex(derivation PublicKey, outputIndex uint64) (PrivateKey, uint8) {
|
||||
|
@ -24,10 +22,9 @@ func GetDerivationSharedDataAndViewTagForOutputIndex(derivation PublicKey, outpu
|
|||
|
||||
n := binary.PutUvarint(varIntBuf[:], outputIndex)
|
||||
pK := PrivateKeyFromScalar(HashToScalar(k[:], varIntBuf[:n]))
|
||||
h := moneroutil.Keccak256([]byte("view_tag"), k[:], varIntBuf[:n])
|
||||
return pK, h[0]
|
||||
return pK, PooledKeccak256([]byte("view_tag"), k[:], varIntBuf[:n])[0]
|
||||
}
|
||||
|
||||
func GetKeyImage(pair *KeyPair) PublicKey {
|
||||
return PublicKeyFromPoint(HashToPoint(pair.PublicKey)).Multiply(pair.PrivateKey.AsScalar())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,29 +3,51 @@ package crypto
|
|||
import (
|
||||
"filippo.io/edwards25519"
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"hash"
|
||||
"io"
|
||||
)
|
||||
|
||||
func BytesToScalar(buf []byte) *edwards25519.Scalar {
|
||||
var bytes [32]byte
|
||||
copy(bytes[:], buf[:])
|
||||
scReduce32(bytes[:])
|
||||
c, _ := edwards25519.NewScalar().SetCanonicalBytes(bytes[:])
|
||||
c, _ := GetEdwards25519Scalar().SetCanonicalBytes(bytes[:])
|
||||
return c
|
||||
}
|
||||
|
||||
func Keccak256(data ...[]byte) (result types.Hash) {
|
||||
h := sha3.NewLegacyKeccak256()
|
||||
for _, b := range data {
|
||||
h.Write(b)
|
||||
}
|
||||
HashFastSum(h, result[:])
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func HashToScalar(data ...[]byte) *edwards25519.Scalar {
|
||||
h := moneroutil.Keccak256(data...)
|
||||
h := PooledKeccak256(data...)
|
||||
scReduce32(h[:])
|
||||
c, _ := edwards25519.NewScalar().SetCanonicalBytes(h[:])
|
||||
c, _ := GetEdwards25519Scalar().SetCanonicalBytes(h[:])
|
||||
return c
|
||||
}
|
||||
|
||||
// HashFastSum sha3.Sum clones the state by allocating memory. prevent that. b must be pre-allocated to the expected size, or larger
|
||||
func HashFastSum(hash hash.Hash, b []byte) []byte {
|
||||
if r, ok := hash.(io.Reader); ok {
|
||||
_, _ = r.Read(b[:hash.Size()])
|
||||
return b
|
||||
}
|
||||
return hash.Sum(b[:0])
|
||||
}
|
||||
|
||||
func HashToPoint(publicKey PublicKey) *edwards25519.Point {
|
||||
//TODO: make this work with existing edwards25519 library
|
||||
input := moneroutil.Key(publicKey.AsBytes())
|
||||
var key moneroutil.Key
|
||||
(&input).HashToEC().ToBytes(&key)
|
||||
p, _ := (&edwards25519.Point{}).SetBytes(key[:])
|
||||
p, _ := GetEdwards25519Point().SetBytes(key[:])
|
||||
return p
|
||||
}
|
||||
|
||||
|
|
11
monero/crypto/hash_test.go
Normal file
11
monero/crypto/hash_test.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package crypto
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestHash(t *testing.T) {
|
||||
h := PooledKeccak256([]byte("test")).String()
|
||||
|
||||
if h != "9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658" {
|
||||
t.Fatalf("got %s, expected %s", h, "9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658")
|
||||
}
|
||||
}
|
63
monero/crypto/pool.go
Normal file
63
monero/crypto/pool.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"filippo.io/edwards25519"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"hash"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var hasherPool, pointPool, scalarPool sync.Pool
|
||||
|
||||
func init() {
|
||||
hasherPool.New = func() any {
|
||||
return sha3.NewLegacyKeccak256()
|
||||
}
|
||||
pointPool.New = func() any {
|
||||
p := new(edwards25519.Point)
|
||||
runtime.SetFinalizer(p, PutEdwards25519Point)
|
||||
return p
|
||||
}
|
||||
scalarPool.New = func() any {
|
||||
s := new(edwards25519.Scalar)
|
||||
runtime.SetFinalizer(s, PutEdwards25519Scalar)
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
func GetKeccak256Hasher() hash.Hash {
|
||||
return hasherPool.Get().(hash.Hash)
|
||||
}
|
||||
|
||||
func PutKeccak256Hasher(h hash.Hash) {
|
||||
h.Reset()
|
||||
hasherPool.Put(h)
|
||||
}
|
||||
|
||||
func PooledKeccak256(data ...[]byte) (result types.Hash) {
|
||||
h := GetKeccak256Hasher()
|
||||
defer PutKeccak256Hasher(h)
|
||||
for _, b := range data {
|
||||
h.Write(b)
|
||||
}
|
||||
HashFastSum(h, result[:])
|
||||
return
|
||||
}
|
||||
|
||||
func GetEdwards25519Point() *edwards25519.Point {
|
||||
return pointPool.Get().(*edwards25519.Point)
|
||||
}
|
||||
|
||||
func PutEdwards25519Point(p *edwards25519.Point) {
|
||||
pointPool.Put(p)
|
||||
}
|
||||
|
||||
func GetEdwards25519Scalar() *edwards25519.Scalar {
|
||||
return scalarPool.Get().(*edwards25519.Scalar)
|
||||
}
|
||||
|
||||
func PutEdwards25519Scalar(s *edwards25519.Scalar) {
|
||||
scalarPool.Put(s)
|
||||
}
|
|
@ -50,7 +50,7 @@ func (p *PrivateKeyScalar) Scalar() *edwards25519.Scalar {
|
|||
}
|
||||
|
||||
func (p *PrivateKeyScalar) PublicKey() PublicKey {
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).ScalarBaseMult(p.Scalar()))
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().ScalarBaseMult(p.Scalar()))
|
||||
}
|
||||
|
||||
func (p *PrivateKeyScalar) GetDerivation(public PublicKey) PublicKey {
|
||||
|
@ -61,7 +61,6 @@ func (p *PrivateKeyScalar) GetDerivationCofactor(public PublicKey) PublicKey {
|
|||
return deriveKeyExchangeSecretCofactor(p, public.AsPoint())
|
||||
}
|
||||
|
||||
|
||||
func (p *PrivateKeyScalar) String() string {
|
||||
return hex.EncodeToString(p.Scalar().Bytes())
|
||||
}
|
||||
|
@ -87,7 +86,6 @@ func (p *PrivateKeyScalar) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
type PrivateKeyBytes [PrivateKeySize]byte
|
||||
|
||||
func (k *PrivateKeyBytes) AsSlice() PrivateKeySlice {
|
||||
|
@ -99,12 +97,12 @@ func (k *PrivateKeyBytes) AsBytes() PrivateKeyBytes {
|
|||
}
|
||||
|
||||
func (k *PrivateKeyBytes) AsScalar() *PrivateKeyScalar {
|
||||
secret, _ := edwards25519.NewScalar().SetCanonicalBytes((*k)[:])
|
||||
secret, _ := GetEdwards25519Scalar().SetCanonicalBytes((*k)[:])
|
||||
return PrivateKeyFromScalar(secret)
|
||||
}
|
||||
|
||||
func (k *PrivateKeyBytes) PublicKey() PublicKey {
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).ScalarBaseMult(k.AsScalar().Scalar()))
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().ScalarBaseMult(k.AsScalar().Scalar()))
|
||||
}
|
||||
|
||||
func (k *PrivateKeyBytes) GetDerivation(public PublicKey) PublicKey {
|
||||
|
@ -115,7 +113,6 @@ func (k *PrivateKeyBytes) GetDerivationCofactor(public PublicKey) PublicKey {
|
|||
return k.AsScalar().GetDerivationCofactor(public)
|
||||
}
|
||||
|
||||
|
||||
func (k *PrivateKeyBytes) String() string {
|
||||
return hex.EncodeToString(k.AsSlice())
|
||||
}
|
||||
|
@ -138,7 +135,6 @@ func (k *PrivateKeyBytes) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
type PrivateKeySlice []byte
|
||||
|
||||
func (k *PrivateKeySlice) AsSlice() PrivateKeySlice {
|
||||
|
@ -151,12 +147,12 @@ func (k *PrivateKeySlice) AsBytes() (buf PrivateKeyBytes) {
|
|||
}
|
||||
|
||||
func (k *PrivateKeySlice) AsScalar() *PrivateKeyScalar {
|
||||
secret, _ := edwards25519.NewScalar().SetCanonicalBytes(*k)
|
||||
secret, _ := GetEdwards25519Scalar().SetCanonicalBytes(*k)
|
||||
return PrivateKeyFromScalar(secret)
|
||||
}
|
||||
|
||||
func (k *PrivateKeySlice) PublicKey() PublicKey {
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).ScalarBaseMult(k.AsScalar().Scalar()))
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().ScalarBaseMult(k.AsScalar().Scalar()))
|
||||
}
|
||||
|
||||
func (k *PrivateKeySlice) GetDerivation(public PublicKey) PublicKey {
|
||||
|
@ -167,7 +163,6 @@ func (k *PrivateKeySlice) GetDerivationCofactor(public PublicKey) PublicKey {
|
|||
return k.AsScalar().GetDerivationCofactor(public)
|
||||
}
|
||||
|
||||
|
||||
func (k *PrivateKeySlice) String() string {
|
||||
return hex.EncodeToString(*k)
|
||||
}
|
||||
|
@ -190,11 +185,10 @@ func (k *PrivateKeySlice) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
func deriveKeyExchangeSecretCofactor(private *PrivateKeyScalar, public *PublicKeyPoint) *PublicKeyPoint {
|
||||
return public.Multiply(private).Cofactor()
|
||||
}
|
||||
|
||||
func deriveKeyExchangeSecret(private *PrivateKeyScalar, public *PublicKeyPoint) *PublicKeyPoint {
|
||||
return public.Multiply(private)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
)
|
||||
|
||||
var TxProofV2DomainSeparatorHash = types.Hash(moneroutil.Keccak256([]byte("TXPROOF_V2"))) // HASH_KEY_TXPROOF_V2
|
||||
var TxProofV2DomainSeparatorHash = Keccak256([]byte("TXPROOF_V2")) // HASH_KEY_TXPROOF_V2
|
||||
func GenerateTxProofV2(prefixHash types.Hash, txKey PrivateKey, recipientViewPublicKey PublicKey, recipientSpendPublicKey PublicKey) (derivation PublicKey, signature *Signature) {
|
||||
comm := &SignatureComm_2{}
|
||||
comm.Message = prefixHash
|
||||
|
|
|
@ -37,20 +37,20 @@ func (k *PublicKeyPoint) Point() *edwards25519.Point {
|
|||
return (*edwards25519.Point)(k)
|
||||
}
|
||||
|
||||
func (k *PublicKeyPoint) Add(b *PublicKeyPoint) *PublicKeyPoint{
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).Add(k.Point(), b.Point()))
|
||||
func (k *PublicKeyPoint) Add(b *PublicKeyPoint) *PublicKeyPoint {
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().Add(k.Point(), b.Point()))
|
||||
}
|
||||
|
||||
func (k *PublicKeyPoint) Subtract(b *PublicKeyPoint) *PublicKeyPoint{
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).Subtract(k.Point(), b.Point()))
|
||||
func (k *PublicKeyPoint) Subtract(b *PublicKeyPoint) *PublicKeyPoint {
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().Subtract(k.Point(), b.Point()))
|
||||
}
|
||||
|
||||
func (k *PublicKeyPoint) Multiply(b *PrivateKeyScalar) *PublicKeyPoint{
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).ScalarMult(b.Scalar(), k.Point()))
|
||||
func (k *PublicKeyPoint) Multiply(b *PrivateKeyScalar) *PublicKeyPoint {
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().ScalarMult(b.Scalar(), k.Point()))
|
||||
}
|
||||
|
||||
func (k *PublicKeyPoint) Cofactor() *PublicKeyPoint{
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).MultByCofactor(k.Point()))
|
||||
func (k *PublicKeyPoint) Cofactor() *PublicKeyPoint {
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().MultByCofactor(k.Point()))
|
||||
}
|
||||
|
||||
func PublicKeyFromPoint(point *edwards25519.Point, _ ...any) *PublicKeyPoint {
|
||||
|
@ -82,8 +82,6 @@ func (k *PublicKeyPoint) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
type PublicKeyBytes [PublicKeySize]byte
|
||||
|
||||
func (k *PublicKeyBytes) AsSlice() PublicKeySlice {
|
||||
|
@ -95,7 +93,7 @@ func (k *PublicKeyBytes) AsBytes() PublicKeyBytes {
|
|||
}
|
||||
|
||||
func (k *PublicKeyBytes) AsPoint() *PublicKeyPoint {
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).SetBytes(k.AsSlice()))
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().SetBytes(k.AsSlice()))
|
||||
}
|
||||
|
||||
func (k *PublicKeyBytes) String() string {
|
||||
|
@ -120,7 +118,6 @@ func (k *PublicKeyBytes) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
type PublicKeySlice []byte
|
||||
|
||||
func (k *PublicKeySlice) AsSlice() PublicKeySlice {
|
||||
|
@ -133,7 +130,7 @@ func (k *PublicKeySlice) AsBytes() (buf PublicKeyBytes) {
|
|||
}
|
||||
|
||||
func (k *PublicKeySlice) AsPoint() *PublicKeyPoint {
|
||||
return PublicKeyFromPoint((&edwards25519.Point{}).SetBytes(*k))
|
||||
return PublicKeyFromPoint(GetEdwards25519Point().SetBytes(*k))
|
||||
}
|
||||
|
||||
func (k *PublicKeySlice) String() string {
|
||||
|
@ -156,4 +153,4 @@ func (k *PublicKeySlice) UnmarshalJSON(b []byte) error {
|
|||
*k = buf
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ func DeterministicScalar(entropy ...[]byte) *edwards25519.Scalar {
|
|||
h := sha3.NewLegacyKeccak256()
|
||||
var hash types.Hash
|
||||
|
||||
scalar := edwards25519.NewScalar()
|
||||
scalar := GetEdwards25519Scalar()
|
||||
|
||||
for {
|
||||
h.Reset()
|
||||
|
|
|
@ -12,10 +12,12 @@ type Signature struct {
|
|||
// R result of the signature, also called s
|
||||
R *edwards25519.Scalar
|
||||
}
|
||||
|
||||
// SignatureSigningHandler receives k, inserts it or a pubkey into its data, and produces a []byte buffer for Signing/Verifying
|
||||
type SignatureSigningHandler func (r PrivateKey) []byte
|
||||
type SignatureSigningHandler func(r PrivateKey) []byte
|
||||
|
||||
// SignatureVerificationHandler receives r = pubkey(k), inserts it into its data, and produces a []byte buffer for Signing/Verifying
|
||||
type SignatureVerificationHandler func (r PublicKey) []byte
|
||||
type SignatureVerificationHandler func(r PublicKey) []byte
|
||||
|
||||
func NewSignatureFromBytes(buf []byte) *Signature {
|
||||
if len(buf) != types.HashSize*2 {
|
||||
|
@ -23,9 +25,9 @@ func NewSignatureFromBytes(buf []byte) *Signature {
|
|||
}
|
||||
signature := &Signature{}
|
||||
var err error
|
||||
if signature.C, err = edwards25519.NewScalar().SetCanonicalBytes(buf[:32]); err != nil {
|
||||
if signature.C, err = GetEdwards25519Scalar().SetCanonicalBytes(buf[:32]); err != nil {
|
||||
return nil
|
||||
} else if signature.R, err = edwards25519.NewScalar().SetCanonicalBytes(buf[32:]); err != nil {
|
||||
} else if signature.R, err = GetEdwards25519Scalar().SetCanonicalBytes(buf[32:]); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
return signature
|
||||
|
@ -42,7 +44,7 @@ func (s *Signature) Bytes() []byte {
|
|||
// Verify checks a Schnorr Signature using H = keccak
|
||||
func (s *Signature) Verify(handler SignatureVerificationHandler, publicKey PublicKey) (ok bool, r *PublicKeyPoint) {
|
||||
//s = C * k, R * G
|
||||
sp := (&edwards25519.Point{}).VarTimeDoubleScalarBaseMult(s.C, publicKey.AsPoint().Point(), s.R)
|
||||
sp := GetEdwards25519Point().VarTimeDoubleScalarBaseMult(s.C, publicKey.AsPoint().Point(), s.R)
|
||||
if sp.Equal(infinityPoint) == 1 {
|
||||
return false, nil
|
||||
}
|
||||
|
@ -62,11 +64,10 @@ func CreateSignature(handler SignatureSigningHandler, privateKey PrivateKey) *Si
|
|||
|
||||
// s = k - x * e
|
||||
// EdDSA is an altered version, with addition instead of subtraction
|
||||
signature.R = signature.R.Subtract(k.Scalar(), edwards25519.NewScalar().Multiply(signature.C, privateKey.AsScalar().Scalar()))
|
||||
signature.R = signature.R.Subtract(k.Scalar(), GetEdwards25519Scalar().Multiply(signature.C, privateKey.AsScalar().Scalar()))
|
||||
return signature
|
||||
}
|
||||
|
||||
|
||||
func CreateMessageSignature(prefixHash types.Hash, key PrivateKey) *Signature {
|
||||
buf := &SignatureComm{}
|
||||
buf.Hash = prefixHash
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"git.gammaspectra.live/P2Pool/randomx-go-bindings"
|
||||
"github.com/go-faster/xor"
|
||||
|
@ -17,7 +17,7 @@ import (
|
|||
)
|
||||
|
||||
type hasherCollection struct {
|
||||
lock sync.RWMutex
|
||||
lock sync.RWMutex
|
||||
index int
|
||||
cache []*hasherState
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func (h *hasherCollection) Close() {
|
|||
}
|
||||
|
||||
type hasherState struct {
|
||||
lock sync.Mutex
|
||||
lock sync.Mutex
|
||||
dataset *randomx.RxDataset
|
||||
vm *randomx.RxVM
|
||||
key []byte
|
||||
|
@ -97,7 +97,7 @@ func ConsensusHash(buf []byte) types.Hash {
|
|||
cachePtr = cachePtr[stride:]
|
||||
}
|
||||
|
||||
return types.Hash(moneroutil.Keccak256(scratchpadTopPtr))
|
||||
return crypto.Keccak256(scratchpadTopPtr)
|
||||
}
|
||||
|
||||
func NewRandomX() Hasher {
|
||||
|
@ -141,7 +141,7 @@ func (h *hasherState) Init(key []byte) (err error) {
|
|||
h.vm.Close()
|
||||
}
|
||||
|
||||
if h.vm, err = randomx.NewRxVM(h.dataset, /*randomx.FlagFullMEM,*/ randomx.FlagHardAES, randomx.FlagJIT, randomx.FlagSecure); err != nil {
|
||||
if h.vm, err = randomx.NewRxVM(h.dataset /*randomx.FlagFullMEM,*/, randomx.FlagHardAES, randomx.FlagJIT, randomx.FlagSecure); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("[RandomX] Initialized to seed %s", hex.EncodeToString(h.key))
|
||||
|
|
|
@ -5,7 +5,7 @@ package randomx
|
|||
import (
|
||||
"bytes"
|
||||
"git.gammaspectra.live/P2Pool/go-randomx"
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"github.com/go-faster/xor"
|
||||
"runtime"
|
||||
|
@ -49,7 +49,7 @@ func ConsensusHash(buf []byte) types.Hash {
|
|||
cachePtr = cachePtr[stride:]
|
||||
}
|
||||
|
||||
return types.Hash(moneroutil.Keccak256(scratchpadTopPtr))
|
||||
return crypto.Keccak256(scratchpadTopPtr)
|
||||
}
|
||||
|
||||
func NewRandomX() Hasher {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"io"
|
||||
|
@ -78,7 +78,6 @@ func (c *CoinbaseTransaction) FromReader(reader readerAndByteReader) (err error)
|
|||
return err
|
||||
}
|
||||
|
||||
|
||||
if err = c.Outputs.FromReader(reader); err != nil {
|
||||
return err
|
||||
} else if len(c.Outputs) != 0 {
|
||||
|
@ -207,6 +206,6 @@ func (c *CoinbaseTransaction) Id() types.Hash {
|
|||
}
|
||||
|
||||
func hashKeccak(data ...[]byte) []byte {
|
||||
d := moneroutil.Keccak256(data...)
|
||||
d := crypto.PooledKeccak256(data...)
|
||||
return d[:]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
@ -9,7 +8,7 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
type Outputs []*Output
|
||||
type Outputs []Output
|
||||
|
||||
|
||||
func (s *Outputs) FromReader(reader readerAndByteReader) (err error) {
|
||||
|
@ -24,10 +23,9 @@ func (s *Outputs) FromReader(reader readerAndByteReader) (err error) {
|
|||
*s = make(Outputs, 0, outputCount)
|
||||
}
|
||||
|
||||
var o Output
|
||||
for index := 0; index < int(outputCount); index++ {
|
||||
o := &Output{
|
||||
Index: uint64(index),
|
||||
}
|
||||
o.Index = uint64(index)
|
||||
|
||||
if o.Reward, err = binary.ReadUvarint(reader); err != nil {
|
||||
return err
|
||||
|
@ -47,6 +45,8 @@ func (s *Outputs) FromReader(reader readerAndByteReader) (err error) {
|
|||
if o.ViewTag, err = reader.ReadByte(); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
o.ViewTag = 0
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unknown %d TXOUT key", o.Type)
|
||||
|
@ -59,28 +59,26 @@ func (s *Outputs) FromReader(reader readerAndByteReader) (err error) {
|
|||
}
|
||||
|
||||
func (s *Outputs) MarshalBinary() (data []byte, err error) {
|
||||
buf := new(bytes.Buffer)
|
||||
data = make([]byte, 0, binary.MaxVarintLen64 + len(*s) * (binary.MaxVarintLen64 + 1 + crypto.PublicKeySize + 1))
|
||||
|
||||
varIntBuf := make([]byte, binary.MaxVarintLen64)
|
||||
|
||||
_, _ = buf.Write(varIntBuf[:binary.PutUvarint(varIntBuf, uint64(len(*s)))])
|
||||
data = binary.AppendUvarint(data, uint64(len(*s)))
|
||||
|
||||
for _, o := range *s {
|
||||
_, _ = buf.Write(varIntBuf[:binary.PutUvarint(varIntBuf, o.Reward)])
|
||||
_ = binary.Write(buf, binary.BigEndian, o.Type)
|
||||
data = binary.AppendUvarint(data, o.Reward)
|
||||
data = append(data, o.Type)
|
||||
|
||||
switch o.Type {
|
||||
case TxOutToTaggedKey, TxOutToKey:
|
||||
_, _ = buf.Write(o.EphemeralPublicKey.AsSlice())
|
||||
data = append(data, o.EphemeralPublicKey[:]...)
|
||||
|
||||
if o.Type == TxOutToTaggedKey {
|
||||
_ = binary.Write(buf, binary.BigEndian, o.ViewTag)
|
||||
data = append(data, o.ViewTag)
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("unknown output type")
|
||||
}
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
return data, nil
|
||||
}
|
||||
|
||||
type Output struct {
|
||||
|
|
|
@ -3,9 +3,8 @@ package p2p
|
|||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -26,24 +25,25 @@ func FindChallengeSolution(challenge HandshakeChallenge, consensusId types.Hash,
|
|||
_, _ = rand.Read(saltSlice[:])
|
||||
salt = binary.LittleEndian.Uint64(saltSlice[:])
|
||||
|
||||
h := sha3.NewLegacyKeccak256()
|
||||
h := crypto.GetKeccak256Hasher()
|
||||
defer crypto.PutKeccak256Hasher(h)
|
||||
|
||||
sum := make([]byte, types.HashSize)
|
||||
var sum types.Hash
|
||||
|
||||
for {
|
||||
h.Reset()
|
||||
binary.LittleEndian.PutUint64(buf[types.HashSize+HandshakeChallengeSize:], salt)
|
||||
_, _ = h.Write(buf[:])
|
||||
sum = h.Sum(sum[:0])
|
||||
crypto.HashFastSum(h, sum[:])
|
||||
|
||||
//check if we have been asked to stop
|
||||
if stop.Load() {
|
||||
return salt, types.HashFromBytes(sum), false
|
||||
return salt, sum, false
|
||||
}
|
||||
|
||||
if types.DifficultyFrom64(binary.LittleEndian.Uint64(sum[len(sum)-int(unsafe.Sizeof(uint64(0))):])).Mul64(HandshakeChallengeDifficulty).Hi == 0 {
|
||||
//found solution
|
||||
return salt, types.HashFromBytes(sum), true
|
||||
return salt, sum, true
|
||||
}
|
||||
|
||||
salt++
|
||||
|
@ -51,6 +51,6 @@ func FindChallengeSolution(challenge HandshakeChallenge, consensusId types.Hash,
|
|||
}
|
||||
|
||||
func CalculateChallengeHash(challenge HandshakeChallenge, consensusId types.Hash, solution uint64) (hash types.Hash, ok bool) {
|
||||
hash = types.Hash(moneroutil.Keccak256(challenge[:], consensusId[:], binary.LittleEndian.AppendUint64(nil, solution)))
|
||||
hash = crypto.PooledKeccak256(challenge[:], consensusId[:], binary.LittleEndian.AppendUint64(nil, solution))
|
||||
return hash, types.DifficultyFrom64(binary.LittleEndian.Uint64(hash[types.HashSize-int(unsafe.Sizeof(uint64(0))):])).Mul64(HandshakeChallengeDifficulty).Hi == 0
|
||||
}
|
||||
|
|
|
@ -24,19 +24,19 @@ const DefaultBanTime = time.Second * 600
|
|||
const PeerListResponseMaxPeers = 16
|
||||
|
||||
type Client struct {
|
||||
Owner *Server
|
||||
Connection net.Conn
|
||||
Closed atomic.Bool
|
||||
AddressPort netip.AddrPort
|
||||
LastActive time.Time
|
||||
LastBroadcast time.Time
|
||||
LastBlockRequest time.Time
|
||||
PingTime time.Duration
|
||||
Owner *Server
|
||||
Connection net.Conn
|
||||
Closed atomic.Bool
|
||||
AddressPort netip.AddrPort
|
||||
LastActive time.Time
|
||||
LastBroadcast time.Time
|
||||
LastBlockRequest time.Time
|
||||
PingTime time.Duration
|
||||
LastPeerListRequestTime time.Time
|
||||
PeerId uint64
|
||||
IsIncomingConnection bool
|
||||
HandshakeComplete atomic.Bool
|
||||
ListenPort uint32
|
||||
PeerId uint64
|
||||
IsIncomingConnection bool
|
||||
HandshakeComplete atomic.Bool
|
||||
ListenPort uint32
|
||||
|
||||
BlockPendingRequests int64
|
||||
ChainTipBlockRequest bool
|
||||
|
@ -61,7 +61,7 @@ func NewClient(owner *Server, conn net.Conn) *Client {
|
|||
expectedMessage: MessageHandshakeChallenge,
|
||||
blockRequestThrottler: time.Tick(time.Second / 50), //maximum 50 per second
|
||||
messageChannel: make(chan *ClientMessage, 10),
|
||||
closeChannel: make(chan struct{}),
|
||||
closeChannel: make(chan struct{}),
|
||||
}
|
||||
|
||||
return c
|
||||
|
@ -80,7 +80,7 @@ func (c *Client) OnAfterHandshake() {
|
|||
func (c *Client) SendListenPort() {
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessageListenPort,
|
||||
Buffer: binary.LittleEndian.AppendUint32(nil, uint32(c.Owner.listenAddress.Port())),
|
||||
Buffer: binary.LittleEndian.AppendUint32(nil, uint32(c.Owner.listenAddress.Port())),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ func (c *Client) SendBlockRequest(hash types.Hash) {
|
|||
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessageBlockRequest,
|
||||
Buffer: hash[:],
|
||||
Buffer: hash[:],
|
||||
})
|
||||
|
||||
c.BlockPendingRequests++
|
||||
|
@ -105,13 +105,13 @@ func (c *Client) SendBlockResponse(block *sidechain.PoolBlock) {
|
|||
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessageBlockResponse,
|
||||
Buffer: append(binary.LittleEndian.AppendUint32(make([]byte, 0, len(blockData)+4), uint32(len(blockData))), blockData...),
|
||||
Buffer: append(binary.LittleEndian.AppendUint32(make([]byte, 0, len(blockData)+4), uint32(len(blockData))), blockData...),
|
||||
})
|
||||
|
||||
} else {
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessageBlockResponse,
|
||||
Buffer: binary.LittleEndian.AppendUint32(nil, 0),
|
||||
Buffer: binary.LittleEndian.AppendUint32(nil, 0),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -122,13 +122,13 @@ func (c *Client) SendBlockBroadcast(block *sidechain.PoolBlock) {
|
|||
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessageBlockBroadcast,
|
||||
Buffer: append(binary.LittleEndian.AppendUint32(make([]byte, 0, len(blockData)+4), uint32(len(blockData))), blockData...),
|
||||
Buffer: append(binary.LittleEndian.AppendUint32(make([]byte, 0, len(blockData)+4), uint32(len(blockData))), blockData...),
|
||||
})
|
||||
|
||||
} else {
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessageBlockBroadcast,
|
||||
Buffer: binary.LittleEndian.AppendUint32(nil, 0),
|
||||
Buffer: binary.LittleEndian.AppendUint32(nil, 0),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ func (c *Client) SendPeerListResponse(list []netip.AddrPort) {
|
|||
if len(list) > PeerListResponseMaxPeers {
|
||||
return
|
||||
}
|
||||
buf := make([]byte, 0, 1 + len(list) * (1 + 16 + 2 ))
|
||||
buf := make([]byte, 0, 1+len(list)*(1+16+2))
|
||||
buf = append(buf, byte(len(list)))
|
||||
for i := range list {
|
||||
if list[i].Addr().Is6() {
|
||||
|
@ -158,7 +158,7 @@ func (c *Client) SendPeerListResponse(list []netip.AddrPort) {
|
|||
}
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessagePeerListResponse,
|
||||
Buffer: buf,
|
||||
Buffer: buf,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ func (c *Client) OnConnection() {
|
|||
select {
|
||||
case <-c.closeChannel:
|
||||
return
|
||||
case message := <- c.messageChannel:
|
||||
case message := <-c.messageChannel:
|
||||
//log.Printf("Sending message %d len %d", message.MessageId, len(message.Buffer))
|
||||
_, _ = c.Write([]byte{byte(message.MessageId)})
|
||||
_, _ = c.Write(message.Buffer)
|
||||
|
@ -449,7 +449,7 @@ func (c *Client) sendHandshakeChallenge() {
|
|||
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessageHandshakeChallenge,
|
||||
Buffer: buf[:],
|
||||
Buffer: buf[:],
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -468,7 +468,7 @@ func (c *Client) sendHandshakeSolution(challenge HandshakeChallenge) {
|
|||
|
||||
c.SendMessage(&ClientMessage{
|
||||
MessageId: MessageHandshakeSolution,
|
||||
Buffer: buf[:],
|
||||
Buffer: buf[:],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -491,7 +491,7 @@ func (c *Client) Read(buf []byte) (n int, err error) {
|
|||
|
||||
type ClientMessage struct {
|
||||
MessageId MessageId
|
||||
Buffer []byte
|
||||
Buffer []byte
|
||||
}
|
||||
|
||||
func (c *Client) SendMessage(message *ClientMessage) {
|
||||
|
|
|
@ -148,7 +148,7 @@ func (s *Server) Connect(addrPort netip.AddrPort) error {
|
|||
return errors.New("peer is already connected as " + clients[0].AddressPort.String())
|
||||
}
|
||||
|
||||
if conn, err := net.Dial("tcp", addrPort.String()); err != nil {
|
||||
if conn, err := net.DialTimeout("tcp", addrPort.String(), time.Second * 10); err != nil {
|
||||
return err
|
||||
} else {
|
||||
s.clientsLock.Lock()
|
||||
|
|
|
@ -9,11 +9,11 @@ import (
|
|||
)
|
||||
|
||||
type deterministicTransactionCacheKey [crypto.PublicKeySize + types.HashSize]byte
|
||||
type ephemeralPublicKeyCacheKey [crypto.PrivateKeySize + crypto.PublicKeySize * 2 + 8]byte
|
||||
type ephemeralPublicKeyCacheKey [crypto.PrivateKeySize + crypto.PublicKeySize*2 + 8]byte
|
||||
|
||||
type ephemeralPublicKeyWithViewTag struct {
|
||||
PublicKey crypto.PublicKeyBytes
|
||||
ViewTag uint8
|
||||
ViewTag uint8
|
||||
}
|
||||
|
||||
type DerivationCache struct {
|
||||
|
@ -43,13 +43,13 @@ func (d *DerivationCache) Clear() {
|
|||
d.ephemeralPublicKeyCache = lru.New[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](pplnsSize * knownMinersPerPplns * outputIdsPerMiner)
|
||||
}
|
||||
|
||||
func (d *DerivationCache) GetEphemeralPublicKey(a address.Interface, txKey crypto.PrivateKey, outputIndex uint64) (crypto.PublicKeyBytes, uint8) {
|
||||
func (d *DerivationCache) GetEphemeralPublicKey(a address.Interface, txKeySlice crypto.PrivateKeySlice, txKeyScalar *crypto.PrivateKeyScalar, outputIndex uint64) (crypto.PublicKeyBytes, uint8) {
|
||||
var key ephemeralPublicKeyCacheKey
|
||||
copy(key[:], txKey.AsSlice())
|
||||
copy(key[:], txKeySlice)
|
||||
copy(key[crypto.PrivateKeySize:], a.ToPackedAddress().Bytes())
|
||||
binary.LittleEndian.PutUint64(key[crypto.PrivateKeySize + crypto.PublicKeySize*2:], outputIndex)
|
||||
binary.LittleEndian.PutUint64(key[crypto.PrivateKeySize+crypto.PublicKeySize*2:], outputIndex)
|
||||
if ephemeralPubKey := d.ephemeralPublicKeyCache.Get(key); ephemeralPubKey == nil {
|
||||
ephemeralPubKey, viewTag := address.GetEphemeralPublicKeyAndViewTag(a, txKey, outputIndex)
|
||||
ephemeralPubKey, viewTag := address.GetEphemeralPublicKeyAndViewTag(a, txKeyScalar, outputIndex)
|
||||
pKB := ephemeralPubKey.AsBytes()
|
||||
d.ephemeralPublicKeyCache.Set(key, ephemeralPublicKeyWithViewTag{PublicKey: pKB, ViewTag: viewTag})
|
||||
return pKB, viewTag
|
||||
|
|
|
@ -3,9 +3,9 @@ package sidechain
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.gammaspectra.live/P2Pool/moneroutil"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero"
|
||||
mainblock "git.gammaspectra.live/P2Pool/p2pool-observer/monero/block"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/randomx"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"strconv"
|
||||
|
@ -139,7 +139,7 @@ func (i *Consensus) CalculateSideTemplateId(main *mainblock.Block, side *SideDat
|
|||
}
|
||||
|
||||
func (i *Consensus) CalculateSideChainIdFromBlobs(mainBlob, sideBlob []byte) types.Hash {
|
||||
return types.Hash(moneroutil.Keccak256(mainBlob, sideBlob, i.id[:]))
|
||||
return crypto.PooledKeccak256(mainBlob, sideBlob, i.id[:])
|
||||
}
|
||||
|
||||
func (i *Consensus) Id() types.Hash {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/address"
|
||||
mainblock "git.gammaspectra.live/P2Pool/p2pool-observer/monero/block"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/transaction"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
|
@ -443,13 +444,18 @@ func (c *SideChain) verifyBlock(block *PoolBlock) (verification error, invalid e
|
|||
} else if rewards := c.SplitReward(totalReward, c.sharesCache); len(rewards) != len(block.Main.Coinbase.Outputs) {
|
||||
return nil, fmt.Errorf("invalid number of outputs, got %d, expected %d", len(block.Main.Coinbase.Outputs), len(rewards))
|
||||
} else {
|
||||
|
||||
//prevent multiple allocations
|
||||
txPrivateKeySlice := block.Side.CoinbasePrivateKey.AsSlice()
|
||||
txPrivateKeyScalar := block.Side.CoinbasePrivateKey.AsScalar()
|
||||
|
||||
results := utils.SplitWork(-2, uint64(len(rewards)), func(workIndex uint64, workerIndex int) error {
|
||||
out := block.Main.Coinbase.Outputs[workIndex]
|
||||
if rewards[workIndex] != out.Reward {
|
||||
return fmt.Errorf("has invalid reward at index %d, got %d, expected %d", workIndex, out.Reward, rewards[workIndex])
|
||||
}
|
||||
|
||||
if ephPublicKey, viewTag := c.cache.GetEphemeralPublicKey(&c.sharesCache[workIndex].Address, &block.Side.CoinbasePrivateKey, workIndex); ephPublicKey != out.EphemeralPublicKey {
|
||||
if ephPublicKey, viewTag := c.cache.GetEphemeralPublicKey(&c.sharesCache[workIndex].Address, txPrivateKeySlice, txPrivateKeyScalar, workIndex); ephPublicKey != out.EphemeralPublicKey {
|
||||
return fmt.Errorf("has incorrect eph_public_key at index %d, got %s, expected %s", workIndex, out.EphemeralPublicKey.String(), ephPublicKey.String())
|
||||
} else if out.Type == transaction.TxOutToTaggedKey && viewTag != out.ViewTag {
|
||||
return fmt.Errorf("has incorrect view tag at index %d, got %d, expected %d", workIndex, out.ViewTag, viewTag)
|
||||
|
@ -606,13 +612,16 @@ func (c *SideChain) calculateOutputs(block *PoolBlock) transaction.Outputs {
|
|||
|
||||
txType := c.GetTransactionOutputType(block.Main.MajorVersion)
|
||||
|
||||
txPrivateKeySlice := block.Side.CoinbasePrivateKey.AsSlice()
|
||||
txPrivateKeyScalar := block.Side.CoinbasePrivateKey.AsScalar()
|
||||
|
||||
_ = utils.SplitWork(-2, n, func(workIndex uint64, workerIndex int) error {
|
||||
output := &transaction.Output{
|
||||
output := transaction.Output{
|
||||
Index: workIndex,
|
||||
Type: txType,
|
||||
}
|
||||
output.Reward = tmpRewards[output.Index]
|
||||
output.EphemeralPublicKey, output.ViewTag = c.cache.GetEphemeralPublicKey(&tmpShares[output.Index].Address, &block.Side.CoinbasePrivateKey, output.Index)
|
||||
output.EphemeralPublicKey, output.ViewTag = c.cache.GetEphemeralPublicKey(&tmpShares[output.Index].Address, txPrivateKeySlice, txPrivateKeyScalar, output.Index)
|
||||
|
||||
outputs[output.Index] = output
|
||||
|
||||
|
@ -657,15 +666,25 @@ func (c *SideChain) SplitReward(reward uint64, shares Shares) (rewards []uint64)
|
|||
return rewards
|
||||
}
|
||||
|
||||
func (c *SideChain) getShares(tip *PoolBlock, shares Shares) Shares {
|
||||
shares = shares[:0]
|
||||
func (c *SideChain) getShares(tip *PoolBlock, preAllocatedShares Shares) Shares {
|
||||
|
||||
var blockDepth uint64
|
||||
|
||||
cur := tip
|
||||
|
||||
index := 0
|
||||
l := len(preAllocatedShares)
|
||||
insert := func(weight uint64, a *address.PackedAddress) {
|
||||
if index < l {
|
||||
preAllocatedShares[index].Weight, preAllocatedShares[index].Address = weight, *a
|
||||
} else {
|
||||
preAllocatedShares = append(preAllocatedShares, &Share{Weight: weight, Address: *a})
|
||||
}
|
||||
index++
|
||||
}
|
||||
|
||||
for {
|
||||
curShare := &Share{Weight: cur.Side.Difficulty.Lo, Address: *cur.GetAddress()}
|
||||
curWeight := cur.Side.Difficulty.Lo
|
||||
|
||||
for _, uncleId := range cur.Side.Uncles {
|
||||
if uncle := c.getPoolBlockByTemplateId(uncleId); uncle == nil {
|
||||
|
@ -680,13 +699,13 @@ func (c *SideChain) getShares(tip *PoolBlock, shares Shares) Shares {
|
|||
// Take some % of uncle's weight into this share
|
||||
product := uncle.Side.Difficulty.Mul64(c.Consensus().UnclePenalty)
|
||||
unclePenalty := product.Div64(100)
|
||||
curShare.Weight += unclePenalty.Lo
|
||||
curWeight += unclePenalty.Lo
|
||||
|
||||
shares = append(shares, &Share{Weight: uncle.Side.Difficulty.Sub(unclePenalty).Lo, Address: *uncle.GetAddress()})
|
||||
insert(uncle.Side.Difficulty.Sub(unclePenalty).Lo, uncle.GetAddress())
|
||||
}
|
||||
}
|
||||
|
||||
shares = append(shares, curShare)
|
||||
insert(curWeight, cur.GetAddress())
|
||||
|
||||
blockDepth++
|
||||
|
||||
|
@ -706,6 +725,8 @@ func (c *SideChain) getShares(tip *PoolBlock, shares Shares) Shares {
|
|||
}
|
||||
}
|
||||
|
||||
shares := preAllocatedShares[:index]
|
||||
|
||||
// Combine shares with the same wallet addresses
|
||||
slices.SortFunc(shares, func(a *Share, b *Share) bool {
|
||||
return a.Address.Compare(&b.Address) < 0
|
||||
|
|
|
@ -244,13 +244,13 @@ func (d Difficulty) StringNumeric() string {
|
|||
var powBase = uint256.NewInt(0).SetBytes32(bytes.Repeat([]byte{0xff}, 32))
|
||||
|
||||
func DifficultyFromPoW(powHash Hash) Difficulty {
|
||||
pow := uint256.NewInt(0).SetBytes32(powHash[:])
|
||||
pow = &uint256.Int{bits.ReverseBytes64(pow[3]), bits.ReverseBytes64(pow[2]), bits.ReverseBytes64(pow[1]), bits.ReverseBytes64(pow[0])}
|
||||
|
||||
if pow.Eq(uint256.NewInt(0)) {
|
||||
if powHash == ZeroHash {
|
||||
return ZeroDifficulty
|
||||
}
|
||||
|
||||
pow := uint256.NewInt(0).SetBytes32(powHash[:])
|
||||
pow = &uint256.Int{bits.ReverseBytes64(pow[3]), bits.ReverseBytes64(pow[2]), bits.ReverseBytes64(pow[1]), bits.ReverseBytes64(pow[0])}
|
||||
|
||||
powResult := uint256.NewInt(0).Div(powBase, pow).Bytes32()
|
||||
return DifficultyFromBytes(powResult[16:])
|
||||
}
|
||||
|
|
|
@ -11,6 +11,10 @@ func SplitWork(routines int, workSize uint64, do func(workIndex uint64, routineI
|
|||
routines = Max(runtime.NumCPU()-routines, 4)
|
||||
}
|
||||
|
||||
if workSize < uint64(routines) {
|
||||
routines = int(workSize)
|
||||
}
|
||||
|
||||
var counter atomic.Uint64
|
||||
|
||||
results := make([]error, routines)
|
||||
|
@ -27,7 +31,7 @@ func SplitWork(routines int, workSize uint64, do func(workIndex uint64, routineI
|
|||
return
|
||||
}
|
||||
|
||||
if err = do(workIndex - 1, routineIndex); err != nil {
|
||||
if err = do(workIndex-1, routineIndex); err != nil {
|
||||
results[routineIndex] = err
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue