diff --git a/go.mod b/go.mod index c3abd1a..9e0d8a7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.gammaspectra.live/P2Pool/edwards25519 v0.0.0-20240405085108-e2f706cb5c00 git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523 git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221027085532-f46adfce03a7 - git.gammaspectra.live/P2Pool/moneroutil v0.0.0-20230722215223-18ecc51ae61e + git.gammaspectra.live/P2Pool/monero-base58 v1.0.0 git.gammaspectra.live/P2Pool/randomx-go-bindings v0.0.0-20230514082649-9c5f18cd5a71 git.gammaspectra.live/P2Pool/sha3 v0.17.0 github.com/dolthub/swiss v0.2.2-0.20240312182618-f4b2babd2bc1 diff --git a/go.sum b/go.sum index f9a49b4..6cdf1d5 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523 h1:oIJ git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523/go.mod h1:TAOAAV972JNDkCzyV5SkbYkKCRvcfhvvFa8LHH4Dg6g= git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221027085532-f46adfce03a7 h1:bzHDuu1IgETKqPBOlIdCE2LaZIJ+ZpROSprNn+fnzd8= git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221027085532-f46adfce03a7/go.mod h1:3kT0v4AMwT/OdorfH2gRWPwoOrUX/LV03HEeBsaXG1c= -git.gammaspectra.live/P2Pool/moneroutil v0.0.0-20230722215223-18ecc51ae61e h1:ropqS9niQR/ZKCUrlmWe+uDH0fLIyAnCIjkEjyTDgA8= -git.gammaspectra.live/P2Pool/moneroutil v0.0.0-20230722215223-18ecc51ae61e/go.mod h1:Wn5QI7XIMHMpEu10pPspW9h3eGmXQPJwh/4/+Gi3G1U= +git.gammaspectra.live/P2Pool/monero-base58 v1.0.0 h1:s8LZxVNc93YEs2NCCNWZ7CKr8RbEb031y6Wkvhn+TS4= +git.gammaspectra.live/P2Pool/monero-base58 v1.0.0/go.mod h1:WWEJy/AdWKxKAruvlKI82brw+DtVlePy0ct3ZiBlc68= git.gammaspectra.live/P2Pool/randomx-go-bindings v0.0.0-20230514082649-9c5f18cd5a71 h1:MgeHHcF+GnCJBWMSzq8XAbc8p/UhNwFruEKCPPJ74YQ= git.gammaspectra.live/P2Pool/randomx-go-bindings v0.0.0-20230514082649-9c5f18cd5a71/go.mod h1:KQaYHIxGXNHNMQELC7xGLu8xouwvP/dN7iGk681BXmk= git.gammaspectra.live/P2Pool/sha3 v0.17.0 h1:CZpB466LPbNVQrUNjQTtQScGDc30xSMkZ6Bmw0W9VuM= diff --git a/monero/address/address.go b/monero/address/address.go index 771f2bf..07ff0ef 100644 --- a/monero/address/address.go +++ b/monero/address/address.go @@ -3,8 +3,9 @@ package address import ( "bytes" "errors" + "git.gammaspectra.live/P2Pool/consensus/v3/monero" "git.gammaspectra.live/P2Pool/consensus/v3/monero/crypto" - "git.gammaspectra.live/P2Pool/moneroutil" + base58 "git.gammaspectra.live/P2Pool/monero-base58" "slices" ) @@ -13,9 +14,13 @@ type Address struct { ViewPub crypto.PublicKeyBytes Network uint8 hasChecksum bool - checksum moneroutil.Checksum + checksum Checksum } +const ChecksumLength = 4 + +type Checksum [ChecksumLength]byte + func (a *Address) Compare(b Interface) int { //compare spend key @@ -53,31 +58,32 @@ func (a *Address) ToPackedAddress() PackedAddress { func FromBase58(address string) *Address { preAllocatedBuf := make([]byte, 0, 69) - raw := moneroutil.DecodeMoneroBase58PreAllocated(preAllocatedBuf, []byte(address)) + raw := base58.DecodeMoneroBase58PreAllocated(preAllocatedBuf, []byte(address)) if len(raw) != 69 { return nil } switch raw[0] { - case moneroutil.MainNetwork, moneroutil.TestNetwork, moneroutil.StageNetwork: + case monero.MainNetwork, monero.TestNetwork, monero.StageNetwork: break - case moneroutil.IntegratedMainNetwork, moneroutil.IntegratedTestNetwork, moneroutil.IntegratedStageNetwork: + case monero.IntegratedMainNetwork, monero.IntegratedTestNetwork, monero.IntegratedStageNetwork: return nil - case moneroutil.SubAddressMainNetwork, moneroutil.SubAddressTestNetwork, moneroutil.SubAddressStageNetwork: + case monero.SubAddressMainNetwork, monero.SubAddressTestNetwork, monero.SubAddressStageNetwork: return nil default: return nil } - checksum := moneroutil.GetChecksum(raw[:65]) - if bytes.Compare(checksum[:], raw[65:]) != 0 { - return nil - } + checksum := crypto.PooledKeccak256(raw[:65]) a := &Address{ - Network: raw[0], - checksum: checksum, - hasChecksum: true, + Network: raw[0], + } + copy(a.checksum[:], checksum[:ChecksumLength]) + a.hasChecksum = true + + if bytes.Compare(a.checksum[:], raw[65:]) != 0 { + return nil } copy(a.SpendPub[:], raw[1:33]) @@ -88,18 +94,18 @@ func FromBase58(address string) *Address { func FromBase58NoChecksumCheck(address []byte) *Address { preAllocatedBuf := make([]byte, 0, 69) - raw := moneroutil.DecodeMoneroBase58PreAllocated(preAllocatedBuf, address) + raw := base58.DecodeMoneroBase58PreAllocated(preAllocatedBuf, address) if len(raw) != 69 { return nil } switch raw[0] { - case moneroutil.MainNetwork, moneroutil.TestNetwork, moneroutil.StageNetwork: + case monero.MainNetwork, monero.TestNetwork, monero.StageNetwork: break - case moneroutil.IntegratedMainNetwork, moneroutil.IntegratedTestNetwork, moneroutil.IntegratedStageNetwork: + case monero.IntegratedMainNetwork, monero.IntegratedTestNetwork, monero.IntegratedStageNetwork: return nil - case moneroutil.SubAddressMainNetwork, moneroutil.SubAddressTestNetwork, moneroutil.SubAddressStageNetwork: + case monero.SubAddressMainNetwork, monero.SubAddressTestNetwork, monero.SubAddressStageNetwork: return nil default: return nil @@ -128,7 +134,7 @@ func FromRawAddress(network uint8, spend, view crypto.PublicKey) *Address { a := &Address{ Network: nice[0], } - copy(a.checksum[:], checksum[:4]) + copy(a.checksum[:], checksum[:ChecksumLength]) a.hasChecksum = true a.SpendPub = spend.AsBytes() @@ -145,7 +151,7 @@ func (a *Address) verifyChecksum() { copy(nice[1+crypto.PublicKeySize:], a.ViewPub.AsSlice()) sum := crypto.PooledKeccak256(nice[:65]) //this race is ok - copy(a.checksum[:], sum[:4]) + copy(a.checksum[:], sum[:ChecksumLength]) a.hasChecksum = true } } @@ -153,14 +159,14 @@ func (a *Address) verifyChecksum() { func (a *Address) ToBase58() []byte { a.verifyChecksum() buf := make([]byte, 0, 95) - return moneroutil.EncodeMoneroBase58PreAllocated(buf, []byte{a.Network}, a.SpendPub.AsSlice(), a.ViewPub.AsSlice(), a.checksum[:]) + return base58.EncodeMoneroBase58PreAllocated(buf, []byte{a.Network}, a.SpendPub.AsSlice(), a.ViewPub.AsSlice(), a.checksum[:]) } func (a *Address) MarshalJSON() ([]byte, error) { a.verifyChecksum() buf := make([]byte, 95+2) buf[0] = '"' - moneroutil.EncodeMoneroBase58PreAllocated(buf[1:1], []byte{a.Network}, a.SpendPub.AsSlice(), a.ViewPub.AsSlice(), a.checksum[:]) + base58.EncodeMoneroBase58PreAllocated(buf[1:1], []byte{a.Network}, a.SpendPub.AsSlice(), a.ViewPub.AsSlice(), a.checksum[:]) buf[len(buf)-1] = '"' return buf, nil } diff --git a/monero/address/crypto.go b/monero/address/crypto.go index 7c5dc3b..c4730d0 100644 --- a/monero/address/crypto.go +++ b/monero/address/crypto.go @@ -6,7 +6,7 @@ import ( p2poolcrypto "git.gammaspectra.live/P2Pool/consensus/v3/p2pool/crypto" "git.gammaspectra.live/P2Pool/consensus/v3/types" "git.gammaspectra.live/P2Pool/edwards25519" - "git.gammaspectra.live/P2Pool/moneroutil" + base58 "git.gammaspectra.live/P2Pool/monero-base58" "git.gammaspectra.live/P2Pool/sha3" "strings" ) @@ -87,7 +87,7 @@ func GetTxProofV2(a Interface, txId types.Hash, txKey crypto.PrivateKey, message sharedSecret, signature := crypto.GenerateTxProofV2(prefixHash, txKey, a.ViewPublicKey(), nil) - return "OutProofV2" + string(moneroutil.EncodeMoneroBase58(sharedSecret.AsSlice())) + string(moneroutil.EncodeMoneroBase58(signature.Bytes())) + return "OutProofV2" + string(base58.EncodeMoneroBase58(sharedSecret.AsSlice())) + string(base58.EncodeMoneroBase58(signature.Bytes())) } func GetTxProofV1(a Interface, txId types.Hash, txKey crypto.PrivateKey, message string) string { @@ -95,7 +95,7 @@ func GetTxProofV1(a Interface, txId types.Hash, txKey crypto.PrivateKey, message sharedSecret, signature := crypto.GenerateTxProofV1(prefixHash, txKey, a.ViewPublicKey(), nil) - return "OutProofV1" + string(moneroutil.EncodeMoneroBase58(sharedSecret.AsSlice())) + string(moneroutil.EncodeMoneroBase58(signature.Bytes())) + return "OutProofV1" + string(base58.EncodeMoneroBase58(sharedSecret.AsSlice())) + string(base58.EncodeMoneroBase58(signature.Bytes())) } type SignatureVerifyResult int @@ -131,7 +131,7 @@ func VerifyMessage(a Interface, message []byte, signature string) SignatureVerif } else { return ResultFail } - raw := moneroutil.DecodeMoneroBase58([]byte(signature[5:])) + raw := base58.DecodeMoneroBase58([]byte(signature[5:])) sig := crypto.NewSignatureFromBytes(raw) @@ -170,7 +170,7 @@ func VerifyMessageFallbackToZero(a Interface, message []byte, signature string) } else { return ResultFail } - raw := moneroutil.DecodeMoneroBase58([]byte(signature[5:])) + raw := base58.DecodeMoneroBase58([]byte(signature[5:])) sig := crypto.NewSignatureFromBytes(raw) diff --git a/monero/address/packed.go b/monero/address/packed.go index 72364ec..6da0af8 100644 --- a/monero/address/packed.go +++ b/monero/address/packed.go @@ -2,7 +2,7 @@ package address import ( "git.gammaspectra.live/P2Pool/consensus/v3/monero/crypto" - "git.gammaspectra.live/P2Pool/moneroutil" + base58 "git.gammaspectra.live/P2Pool/monero-base58" "unsafe" ) @@ -78,7 +78,7 @@ func (p PackedAddress) ToBase58(network uint8, err ...error) []byte { sum := crypto.PooledKeccak256(nice[:65]) buf := make([]byte, 0, 95) - return moneroutil.EncodeMoneroBase58PreAllocated(buf, []byte{network}, p[PackedAddressSpend][:], p[PackedAddressView][:], sum[:4]) + return base58.EncodeMoneroBase58PreAllocated(buf, []byte{network}, p[PackedAddressSpend][:], p[PackedAddressView][:], sum[:4]) } func (p PackedAddress) Reference() *PackedAddress { diff --git a/monero/constants.go b/monero/constants.go index d6619b7..77b818f 100644 --- a/monero/constants.go +++ b/monero/constants.go @@ -15,3 +15,17 @@ const ( RequiredMoneroVersion = (RequiredMajor << 16) | RequiredMinor RequiredMoneroString = "v0.18.0.0" ) + +const ( + MainNetwork = 18 + TestNetwork = 53 + StageNetwork = 24 + + SubAddressMainNetwork = 42 + SubAddressTestNetwork = 63 + SubAddressStageNetwork = 36 + + IntegratedMainNetwork = 19 + IntegratedTestNetwork = 54 + IntegratedStageNetwork = 25 +) diff --git a/monero/crypto/derivations.go b/monero/crypto/derivations.go index 1f82dbf..1ec847c 100644 --- a/monero/crypto/derivations.go +++ b/monero/crypto/derivations.go @@ -53,6 +53,8 @@ func GetDerivationSharedDataAndViewTagForOutputIndexNoAllocate(k PublicKeyBytes, return c, h[0] } +/* TODO: wait for HashToPoint in edwards25519 func GetKeyImage(pair *KeyPair) PublicKey { return PublicKeyFromPoint(HashToPoint(pair.PublicKey)).Multiply(pair.PrivateKey.AsScalar()) } +*/ diff --git a/monero/crypto/derivations_test.go b/monero/crypto/derivations_test.go index c6e1aad..ff324e5 100644 --- a/monero/crypto/derivations_test.go +++ b/monero/crypto/derivations_test.go @@ -1,11 +1,6 @@ package crypto -import ( - "git.gammaspectra.live/P2Pool/edwards25519" - fasthex "github.com/tmthrgd/go-hex" - "testing" -) - +/* TODO: wait for HashToPoint in edwards25519 func TestKeyImageRaw(t *testing.T) { sec, _ := fasthex.DecodeString("981d477fb18897fa1f784c89721a9d600bf283f06b89cb018a077f41dcefef0f") @@ -16,3 +11,4 @@ func TestKeyImageRaw(t *testing.T) { t.Fatalf("key image expected %s, got %s", "a637203ec41eab772532d30420eac80612fce8e44f1758bc7e2cb1bdda815887", keyImage.String()) } } +*/ diff --git a/monero/crypto/hash.go b/monero/crypto/hash.go index 0a052af..d9a3ac2 100644 --- a/monero/crypto/hash.go +++ b/monero/crypto/hash.go @@ -3,7 +3,6 @@ package crypto import ( "git.gammaspectra.live/P2Pool/consensus/v3/types" "git.gammaspectra.live/P2Pool/edwards25519" - "git.gammaspectra.live/P2Pool/moneroutil" "git.gammaspectra.live/P2Pool/sha3" ) @@ -66,11 +65,58 @@ func HashFastSum(hash *sha3.HasherState, b []byte) []byte { return b } +/* TODO: wait for HashToPoint in edwards25519 + +// HashToPoint Equivalent of Monero's HashToEC +func HashToPointOld(publicKey PublicKey) *edwards25519.Point { + + p := moneroutil.Key(publicKey.AsBytes()) + var key moneroutil.Key + + result := new(moneroutil.ExtendedGroupElement) + var p1 moneroutil.ProjectiveGroupElement + var p2 moneroutil.CompletedGroupElement + h := moneroutil.Key(Keccak256(p[:])) + + log.Printf("old %s", hex.EncodeToString(h[:])) + + p1.FromBytes(&h) + + p1.ToBytes(&key) + log.Printf("old t %s", hex.EncodeToString(key[:])) + + moneroutil.GeMul8(&p2, &p1) + p2.ToExtended(result) + + result.ToBytes(&key) + log.Printf("old c %s", hex.EncodeToString(key[:])) + out, _ := GetEdwards25519Point().SetBytes(key[:]) + return out +} + +var cofactor = new(field.Element).Mult32(new(field.Element).One(), 8) + +// HashToPoint Equivalent of Monero's HashToEC 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, _ := GetEdwards25519Point().SetBytes(key[:]) + h := Keccak256Single(publicKey.AsSlice()) + + log.Printf("new %s", hex.EncodeToString(h[:])) + + e, err := new(field.Element).SetBytes(h[:]) + if err != nil { + panic("hash to point failed") + } + log.Printf("new t %s", hex.EncodeToString(e.Bytes())) + e.Multiply(cofactor, e) + + log.Printf("new c %s", hex.EncodeToString(e.Bytes())) + p, _ := GetEdwards25519Point().SetBytes(e.Bytes()) + return p + + var p1 edwards25519.Point + p1.MultByCofactor(&p1) return p } + +*/ diff --git a/p2pool/sidechain/consensus.go b/p2pool/sidechain/consensus.go index 6398840..bf7a328 100644 --- a/p2pool/sidechain/consensus.go +++ b/p2pool/sidechain/consensus.go @@ -8,7 +8,6 @@ import ( "git.gammaspectra.live/P2Pool/consensus/v3/monero/randomx" "git.gammaspectra.live/P2Pool/consensus/v3/types" "git.gammaspectra.live/P2Pool/consensus/v3/utils" - "git.gammaspectra.live/P2Pool/moneroutil" "strconv" ) @@ -48,11 +47,11 @@ func (n NetworkType) AddressNetwork() (uint8, error) { case NetworkInvalid: return 0, errors.New("invalid network") case NetworkMainnet: - return moneroutil.MainNetwork, nil + return monero.MainNetwork, nil case NetworkTestnet: - return moneroutil.TestNetwork, nil + return monero.TestNetwork, nil case NetworkStagenet: - return moneroutil.StageNetwork, nil + return monero.StageNetwork, nil } return 0, errors.New("unknown network") }