diff --git a/x/claim/client/offchain/cli.go b/x/claim/client/offchain/cli.go index d57dcf2b..aa987283 100644 --- a/x/claim/client/offchain/cli.go +++ b/x/claim/client/offchain/cli.go @@ -1,10 +1,8 @@ package offchain import ( - "encoding/hex" "fmt" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/spf13/cobra" ) @@ -58,24 +56,21 @@ func CmdSignMessage() *cobra.Command { Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { - clientCtx := client.GetClientContextFromCmd(cmd) - fmt.Println(clientCtx) - data := args[0] privateKey := args[1] - signature, err := signData(data, privateKey) + signedData := &SignedData{} + + signedData.sign(data, privateKey) + signedDataString, err := signedData.getSignedDataString() if err != nil { return err } - fmt.Println(hex.EncodeToString(signature)) + fmt.Println(signedDataString) return nil }, } - - flags.AddTxFlagsToCmd(cmd) - return cmd } diff --git a/x/claim/client/offchain/sign.go b/x/claim/client/offchain/sign.go index d7cdc5cd..feb4c8e4 100644 --- a/x/claim/client/offchain/sign.go +++ b/x/claim/client/offchain/sign.go @@ -3,23 +3,53 @@ package offchain import ( "crypto/sha256" "encoding/hex" + "encoding/json" + "fmt" + "strings" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" ) -func signData(data string, privateKey string) ([]byte, error) { +type SignedData struct { + Signature string `json:"proof_signature"` + ProofPubkey string `json:"proof_pubkey"` +} +func (s *SignedData) sign(data string, privateKey string) error { privKeyBytes, err := hex.DecodeString(privateKey) if err != nil { - return nil, err + return err } privKey := secp256k1.PrivKey{Key: privKeyBytes} hash := sha256.Sum256([]byte(data)) signature, err := privKey.Sign(hash[:]) if err != nil { - return nil, err + return err + } + + s.Signature = hex.EncodeToString(signature) + + const prefix = "PubKeySecp256k1{" + const suffix = "}" + + if !strings.HasPrefix(privKey.PubKey().String(), prefix) || !strings.HasSuffix(privKey.PubKey().String(), suffix) { + return fmt.Errorf("invalid pubkey format") + } + + publicKey := strings.TrimPrefix(privKey.PubKey().String(), prefix) + publicKey = strings.TrimSuffix(publicKey, suffix) + + s.ProofPubkey = publicKey + return nil +} + +func (s *SignedData) getSignedDataString() (string, error) { + + jsonData, err := json.Marshal(s) + if err != nil { + return "", fmt.Errorf("failed to marshall signed data: %w", err) } - return signature, nil + return string(jsonData), nil } diff --git a/x/claim/client/offchain/thor_tx_data.go b/x/claim/client/offchain/thor_tx_data.go index edbabfa0..1e3f9f54 100644 --- a/x/claim/client/offchain/thor_tx_data.go +++ b/x/claim/client/offchain/thor_tx_data.go @@ -46,12 +46,12 @@ func fetchThorChainTxData(hash string) (string, error) { } txDataHash := sha512.Sum512(resultBytes) - txHashBase64 := hex.EncodeToString(txDataHash[:]) - txDataBase64 := hex.EncodeToString(resultBytes) + txHashHex := hex.EncodeToString(txDataHash[:]) + txDataHex := hex.EncodeToString(resultBytes) txData := types.ThorTxData{ - Hash: txHashBase64, - TxData: txDataBase64, + Hash: txHashHex, + TxData: txDataHex, } txDataBytes, err := json.Marshal(txData) diff --git a/x/claim/keeper/msg_server_claim_thorchain.go b/x/claim/keeper/msg_server_claim_thorchain.go index a4aba7f1..3ca0c9e8 100644 --- a/x/claim/keeper/msg_server_claim_thorchain.go +++ b/x/claim/keeper/msg_server_claim_thorchain.go @@ -1,6 +1,7 @@ package keeper import ( + "crypto/sha256" "crypto/sha512" "encoding/hex" "encoding/json" @@ -8,73 +9,103 @@ import ( "strings" "github.com/arkeonetwork/arkeo/x/claim/types" + crypto "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" ) // Verify and update the claim record based on the memo of the thorchain tx func (k msgServer) updateThorClaimRecord(ctx sdk.Context, creator string, thorTxMsg *types.MsgThorTxData, arkeoClaimRecord types.ClaimRecord) (types.ClaimRecord, error) { - thorDataDecoded, err := hex.DecodeString(thorTxMsg.ThorData) + // decode thorTxMessage + thorTxMsgDecoded, err := hex.DecodeString(thorTxMsg.ThorData) if err != nil { return types.ClaimRecord{}, fmt.Errorf("error hex decoding faild: %w", err) } - var thorData *types.ThorTxData - if err := json.Unmarshal(thorDataDecoded, &thorData); err != nil { + + // unmarshall encoded data + var thorTxEncodedData *types.ThorTxData + if err := json.Unmarshal(thorTxMsgDecoded, &thorTxEncodedData); err != nil { return types.ClaimRecord{}, fmt.Errorf("error unmarshalling transaction data: %w", err) } - hexDecodeTxData, err := hex.DecodeString(thorData.TxData) + // decode tx data + thorTxDataDecoded, err := hex.DecodeString(thorTxEncodedData.TxData) if err != nil { return types.ClaimRecord{}, fmt.Errorf("error hex decoding failed: %w", err) } - var thorTxData *types.ThorChainTxData - if err := json.Unmarshal(hexDecodeTxData, &thorTxData); err != nil { + // unmarshall thor tx + var thorTxChainData *types.ThorChainTxData + if err := json.Unmarshal(thorTxDataDecoded, &thorTxChainData); err != nil { return types.ClaimRecord{}, fmt.Errorf("error unmarshalling transaction data: %w", err) } - marshalledtxBytes, err := json.Marshal(thorTxData) + // For Reverification of Hash + thorTxChainDataBytes, err := json.Marshal(thorTxChainData) if err != nil { return types.ClaimRecord{}, fmt.Errorf("error marshalling tx data: %w", err) } - txDataHash := sha512.Sum512(marshalledtxBytes) - verifyTxData := hex.EncodeToString(txDataHash[:]) + txDataHash := sha512.Sum512(thorTxChainDataBytes) + verifyTxDataHash := hex.EncodeToString(txDataHash[:]) + txDataHex := hex.EncodeToString(thorTxChainDataBytes) - if verifyTxData != thorData.Hash { + // Verify Data Check Sum + if verifyTxDataHash != thorTxEncodedData.Hash { return types.ClaimRecord{}, fmt.Errorf("transaction data cehcksum failed") } - thorAddress := thorTxData.ObservedTx.Tx.FromAddress - memo := thorTxData.ObservedTx.Tx.Memo + txData := types.ThorTxData{ + Hash: verifyTxDataHash, + TxData: txDataHex, + } - thorAddressBytes, err := sdk.GetFromBech32(thorAddress, "thor") + txDataBytes, err := json.Marshal(txData) if err != nil { - return types.ClaimRecord{}, fmt.Errorf("invalid thorchain address: %w", err) + return types.ClaimRecord{}, fmt.Errorf("error marshalling txData: %w", err) } - prefix := sdk.GetConfig().GetBech32AccountAddrPrefix() - // Re-encode the raw bytes with the new prefix - thorDerivedArkeoAddress, err := sdk.Bech32ifyAddressBytes(prefix, thorAddressBytes) + txDataHashForVerification := hex.EncodeToString(txDataBytes) if err != nil { - return types.ClaimRecord{}, fmt.Errorf("failed to encode address bytes with new prefix: %w", err) + return types.ClaimRecord{}, fmt.Errorf("error hex decoding faild: %w", err) } - decodedPubKey, err := hex.DecodeString(thorTxMsg.ProofPubkey) + // verify the tx signature + proofPubKeyDecoded, err := hex.DecodeString(thorTxMsg.ProofPubkey) if err != nil { - return types.ClaimRecord{}, fmt.Errorf("error in decoding pubkey: %w", err) + return types.ClaimRecord{}, fmt.Errorf("failed to decode pub key: %w", err) } + pubkey := crypto.PubKey{} + pubkey.Key = proofPubKeyDecoded - proofAddress, err := sdk.Bech32ifyAddressBytes(prefix, decodedPubKey) + proofSignatureDecoded, err := hex.DecodeString(thorTxMsg.ProofSignature) if err != nil { - return types.ClaimRecord{}, fmt.Errorf("invalid thorchain address: %w", err) + return types.ClaimRecord{}, fmt.Errorf("failed to decode signature key: %w", err) } - // TODO FIX ME + // create data to verify + + hash := sha256.Sum256([]byte(txDataHashForVerification)) - if proofAddress != thorDerivedArkeoAddress { - return types.ClaimRecord{}, fmt.Errorf("address validation failed: %s , %s", proofAddress, thorDerivedArkeoAddress) + if !pubkey.VerifySignature(hash[:], proofSignatureDecoded[:]) { + return types.ClaimRecord{}, fmt.Errorf("message verification failed") + } + + thorAddress := thorTxChainData.ObservedTx.Tx.FromAddress + memo := thorTxChainData.ObservedTx.Tx.Memo + + thorAddressBytes, err := sdk.GetFromBech32(thorAddress, "thor") + if err != nil { + return types.ClaimRecord{}, fmt.Errorf("invalid thorchain address: %w", err) + } + prefix := sdk.GetConfig().GetBech32AccountAddrPrefix() + + // Re-encode the raw bytes with the new prefix + thorDerivedArkeoAddress, err := sdk.Bech32ifyAddressBytes(prefix, thorAddressBytes) + if err != nil { + return types.ClaimRecord{}, fmt.Errorf("failed to encode address bytes with new prefix: %w", err) } thorClaimRecord, err := k.GetClaimRecord(ctx, thorDerivedArkeoAddress, types.ARKEO) diff --git a/x/claim/keeper/msg_server_claim_thorchain_test.go b/x/claim/keeper/msg_server_claim_thorchain_test.go index 1237cdd1..b5a327fe 100644 --- a/x/claim/keeper/msg_server_claim_thorchain_test.go +++ b/x/claim/keeper/msg_server_claim_thorchain_test.go @@ -47,7 +47,7 @@ func TestClaimThorchainArkeo(t *testing.T) { ThorTxData: &types.MsgThorTxData{ ThorData: "7b2268617368223a223133373430646435623638613938356662386364333464323737353230373039643637653065623939633665356631663430333036366233393662336566656533306138663765653539303165663432313535393036636561626439356538393834323132353439643235336536303034346133366361643934346538383835222c2274785f64617461223a223762323236663632373336353732373636353634356637343738323233613762323237343738323233613762323236393634323233613232343634313332333733363338343134353432333533323431343533303431333333373338333333373332343233343338343233313330343333353432333333373334343233323335343533383432333233303330333534333337333033323431343134343334333433313432333833313333343534343332343633313337333432323263323236333638363136393665323233613232353434383466353232323263323236363732366636643566363136343634373236353733373332323361323237343638366637323331363436633663363637393730333533373663333437383661333537353664373136363633373137393336363333323663333337383636366233303731366233363637373236343334366133383232326332323734366635663631363436343732363537333733323233613232373436383666373233313637333933383633373933333665333936643664366137323730366533303733373836643665333633333663376137343635366336353732363133333337366533383665333633373633333032323263323236333666363936653733323233613562376232323631373337333635373432323361323235343438346635323265353235353465343532323263323236313664366637353665373432323361323233303232376435643263323236373631373332323361366537353663366332633232366436353664366632323361323236343635366336353637363137343635336136313732366236353666336137343631373236623635366633313339333333353338376133323336366137373638333336353334373236343336373037333738373136363338373133363636333337303635333636363338373333373736333037383332363132323764376432633232363336663665373336353665373337353733356636383635363936373638373432323361333133353331333833333334333333303263323236363639366536313663363937333635363435663638363536393637363837343232336133313335333133383333333433333330326332323662363537393733363936373665356636643635373437323639363332323361376232323734373835663639363432323361323234363431333233373336333834313435343233353332343134353330343133333337333833333337333234323334333834323331333034333335343233333337333434323332333534353338343233323330333033353433333733303332343134313434333433343331343233383331333334353434333234363331333733343232326332323665366636343635356637343733373335663734363936643635373332323361366537353663366337643764227d", ProofSignature: "8af1915a046a5b3a11a1c4bf5f8f30f6e05a590a1b3361f69ee8797dd4e6a3ad7679d7fcf359c500cf71d645a215c888ab3e39b8082b2c5975ad5ed8d5004c44", - ProofPubkey: "61726b656f70756231616464776e706570716778676c75786e6634393461656d65327338763571756d726b6b716c726b6c61786c786173336e346639356c37783764366c6376723866703477", + ProofPubkey: "020C8FF0D34D4B5EE779540ECA039B1DAC0F8EDFE9BE6EC233AA4B4FF8DE6EBF86", }, } _, err = msgServer.ClaimArkeo(ctx, &claimMessage) @@ -137,9 +137,9 @@ func TestClaimThorchainEth(t *testing.T) { EthAddress: addrEth, Signature: sigString, ThorTx: &types.MsgThorTxData{ - ThorData: "eyJoYXNoIjoiRTNRTjFiYUttRi00elRUU2QxSUhDZFotRHJtY2JsOGZRREJtczVhejctNHdxUGZ1V1FIdlFoVlpCczZyMlY2SmhDRWxTZEpUNWdCRW8yeXRsRTZJaFEiLCJ0eF9kYXRhIjoiZXlKdlluTmxjblpsWkY5MGVDSTZleUowZUNJNmV5SnBaQ0k2SWtaQk1qYzJPRUZGUWpVeVFVVXdRVE0zT0RNM01rSTBPRUl4TUVNMVFqTTNORUl5TlVVNFFqSXdNRFZETnpBeVFVRkVORFF4UWpneE0wVkVNa1l4TnpRaUxDSmphR0ZwYmlJNklsUklUMUlpTENKbWNtOXRYMkZrWkhKbGMzTWlPaUowYUc5eU1XUnNiR1o1Y0RVM2JEUjRhalYxYlhGbVkzRjVObU15YkRONFptc3djV3MyWjNKa05HbzRJaXdpZEc5ZllXUmtjbVZ6Y3lJNkluUm9iM0l4WnprNFkza3piamx0YldweWNHNHdjM2h0YmpZemJIcDBaV3hsY21Fek4yNDRialkzWXpBaUxDSmpiMmx1Y3lJNlczc2lZWE56WlhRaU9pSlVTRTlTTGxKVlRrVWlMQ0poYlc5MWJuUWlPaUl3SW4xZExDSm5ZWE1pT201MWJHd3NJbTFsYlc4aU9pSmtaV3hsWjJGMFpUcGhjbXRsYnpwMFlYSnJaVzh4T1RNMU9Ib3lObXAzYURObE5ISmtObkJ6ZUhGbU9IRTJaak53WlRabU9ITTNkakI0TW1FaWZYMHNJbU52Ym5ObGJuTjFjMTlvWldsbmFIUWlPakUxTVRnek5ETXdMQ0ptYVc1aGJHbHpaV1JmYUdWcFoyaDBJam94TlRFNE16UXpNQ3dpYTJWNWMybG5ibDl0WlhSeWFXTWlPbnNpZEhoZmFXUWlPaUpHUVRJM05qaEJSVUkxTWtGRk1FRXpOemd6TnpKQ05EaENNVEJETlVJek56UkNNalZGT0VJeU1EQTFRemN3TWtGQlJEUTBNVUk0TVRORlJESkdNVGMwSWl3aWJtOWtaVjkwYzNOZmRHbHRaWE1pT201MWJHeDlmUSJ9", - ProofSignature: "38426dd3b2a9955d5f37bbed4dfe202e1279678366564455066346eed76a2331073ee7226ad81b9dbb8bc3432caebece9f642593242b3f60e2ff9c02127a7f63", - ProofPubkey: "arkeopub1addwnpepqgxgluxnf494aeme2s8v5qumrkkqlrklaxlxas3n4f95l7x7d6lcvr8fp4w", + ThorData: "7b2268617368223a223133373430646435623638613938356662386364333464323737353230373039643637653065623939633665356631663430333036366233393662336566656533306138663765653539303165663432313535393036636561626439356538393834323132353439643235336536303034346133366361643934346538383835222c2274785f64617461223a223762323236663632373336353732373636353634356637343738323233613762323237343738323233613762323236393634323233613232343634313332333733363338343134353432333533323431343533303431333333373338333333373332343233343338343233313330343333353432333333373334343233323335343533383432333233303330333534333337333033323431343134343334333433313432333833313333343534343332343633313337333432323263323236333638363136393665323233613232353434383466353232323263323236363732366636643566363136343634373236353733373332323361323237343638366637323331363436633663363637393730333533373663333437383661333537353664373136363633373137393336363333323663333337383636366233303731366233363637373236343334366133383232326332323734366635663631363436343732363537333733323233613232373436383666373233313637333933383633373933333665333936643664366137323730366533303733373836643665333633333663376137343635366336353732363133333337366533383665333633373633333032323263323236333666363936653733323233613562376232323631373337333635373432323361323235343438346635323265353235353465343532323263323236313664366637353665373432323361323233303232376435643263323236373631373332323361366537353663366332633232366436353664366632323361323236343635366336353637363137343635336136313732366236353666336137343631373236623635366633313339333333353338376133323336366137373638333336353334373236343336373037333738373136363338373133363636333337303635333636363338373333373736333037383332363132323764376432633232363336663665373336353665373337353733356636383635363936373638373432323361333133353331333833333334333333303263323236363639366536313663363937333635363435663638363536393637363837343232336133313335333133383333333433333330326332323662363537393733363936373665356636643635373437323639363332323361376232323734373835663639363432323361323234363431333233373336333834313435343233353332343134353330343133333337333833333337333234323334333834323331333034333335343233333337333434323332333534353338343233323330333033353433333733303332343134313434333433343331343233383331333334353434333234363331333733343232326332323665366636343635356637343733373335663734363936643635373332323361366537353663366337643764227d", + ProofSignature: "8af1915a046a5b3a11a1c4bf5f8f30f6e05a590a1b3361f69ee8797dd4e6a3ad7679d7fcf359c500cf71d645a215c888ab3e39b8082b2c5975ad5ed8d5004c44", + ProofPubkey: "020C8FF0D34D4B5EE779540ECA039B1DAC0F8EDFE9BE6EC233AA4B4FF8DE6EBF86", }, }