Skip to content

Commit

Permalink
chore: verify TX for user smart contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
maharifu committed Aug 20, 2024
1 parent 4f639af commit fd7a594
Show file tree
Hide file tree
Showing 11 changed files with 376 additions and 114 deletions.
6 changes: 3 additions & 3 deletions proto/palomachain/paloma/evm/turnstone.proto
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ message UploadSmartContract {

message UploadUserSmartContract {
bytes bytecode = 1;
string deployer_address = 2;
string deployerAddress = 2;
int64 deadline = 3;

string author = 4 [ (cosmos_proto.scalar) = "cosmos.AddressString" ];
int64 block_height = 5;
bytes senderAddress = 4;
int64 blockHeight = 5;
uint64 id = 6;
uint32 retries = 7;

Expand Down
15 changes: 13 additions & 2 deletions x/evm/keeper/attest_upload_user_smart_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ func (a *uploadUserSmartContractAttester) attest(
ctx sdk.Context,
evidence *types.TxExecutedProof,
) error {
_, err := attestTransactionIntegrity(ctx, a.originalMessage, a.k, evidence,
a.chainReferenceID, a.msg.AssigneeRemoteAddress, a.action.VerifyAgainstTX)
if err != nil {
a.logger.WithError(err).Error("Failed to verify transaction integrity.")
return err
}

tx, err := evidence.GetTX()
if err != nil {
return fmt.Errorf("failed to get TX: %w", err)
Expand All @@ -76,8 +83,10 @@ func (a *uploadUserSmartContractAttester) attest(

contractAddr := crypto.CreateAddress(ethMsg.From, tx.Nonce())

author := sdk.ValAddress(a.action.SenderAddress)

// Update user smart contract deployment
return a.k.SetUserSmartContractDeploymentActive(ctx, a.action.Author,
return a.k.SetUserSmartContractDeploymentActive(ctx, author.String(),
a.action.Id, a.action.BlockHeight, a.chainReferenceID, contractAddr.String())
}

Expand All @@ -88,7 +97,9 @@ func (a *uploadUserSmartContractAttester) attemptRetry(ctx sdk.Context) {
"retries", a.action.Retries,
"chain-reference-id", a.chainReferenceID)

err := a.k.SetUserSmartContractDeploymentError(ctx, a.action.Author,
author := sdk.ValAddress(a.action.SenderAddress)

err := a.k.SetUserSmartContractDeploymentError(ctx, author.String(),
a.action.Id, a.action.BlockHeight, a.chainReferenceID)
if err != nil {
a.logger.WithError(err).Error("Failed to set UserSmartContract error")
Expand Down
73 changes: 62 additions & 11 deletions x/evm/keeper/attest_upload_user_smart_contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ package keeper

import (
"encoding/hex"
"math/big"
"os"

codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
ethcoretypes "github.com/ethereum/go-ethereum/core/types"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/palomachain/paloma/testutil/sample"
consensusmocks "github.com/palomachain/paloma/x/consensus/keeper/consensus/mocks"
consensustypes "github.com/palomachain/paloma/x/consensus/types"
"github.com/palomachain/paloma/x/evm/types"
Expand All @@ -27,7 +33,8 @@ var _ = Describe("attest upload user smart contract", func() {
evidence []*consensustypes.Evidence
retries uint32
)
valAddr := "palomavaloper1tsu8nthuspe4zlkejtj3v27rtq8qz7q6983zt2"

valAddr := "cosmosvaloper1pzf9apnk8yw7pjw3v9vtmxvn6guhkslanh8r07"

testChain := &types.AddChainProposal{
ChainReferenceID: "eth-main",
Expand All @@ -37,11 +44,15 @@ var _ = Describe("attest upload user smart contract", func() {
BlockHashAtHeight: "0x1234",
}

compassABI, _ := os.ReadFile("testdata/sample-abi.json")
compassBytecode, _ := os.ReadFile("testdata/sample-bytecode.out")
txData, _ := os.ReadFile("testdata/user-smart-contract-tx-data.hex")

testContract := &types.UserSmartContract{
Author: valAddr,
Title: "Test Contract",
AbiJson: sample.SimpleABI,
Bytecode: "0x01",
AbiJson: string(compassABI),
Bytecode: string(compassBytecode),
ConstructorInput: "0x00",
}

Expand Down Expand Up @@ -85,32 +96,72 @@ var _ = Describe("attest upload user smart contract", func() {
})

JustBeforeEach(func() {
bytecode, _ := hex.DecodeString("0x00")
senderAddr, _ := sdk.ValAddressFromBech32(valAddr)

consensusMsg, err := codectypes.NewAnyWithValue(&types.Message{
Action: &types.Message_UploadUserSmartContract{
UploadUserSmartContract: &types.UploadUserSmartContract{
Id: 1,
Author: valAddr,
BlockHeight: ctx.BlockHeight(),
Retries: retries,
Bytecode: bytecode,
Id: 1,
SenderAddress: senderAddr,
BlockHeight: ctx.BlockHeight(),
Retries: retries,
Fees: &types.Fees{
RelayerFee: 1,
CommunityFee: 2,
SecurityFee: 3,
},
},
},
})
Expect(err).To(BeNil())

sig := make([]byte, 100)
msg = &consensustypes.QueuedSignedMessage{
Id: 123,
Msg: consensusMsg,
Evidence: evidence,
SignData: []*consensustypes.SignData{{
ExternalAccountAddress: "addr1",
Signature: sig,
}, {
ExternalAccountAddress: "addr2",
Signature: sig,
}},
}
})

Context("attesting with success proof", func() {
var contractAddr string
BeforeEach(func() {
serializedTx, _ := hex.DecodeString("02f87201108405f5e100850b68a0aa00825208941f9c2e67dbbe4c457a5e2be0bc31e67ce5953a2d87470de4df82000080c001a0e05de0771f8d577ec5aa440612c0e8f560d732d5162db0187cfaf56ac50c3716a0147565f4b0924a5adda25f55330c385448e0507d1219d4dac0950e2872682124")
tx := ethcoretypes.NewTx(&ethcoretypes.DynamicFeeTx{
ChainID: big.NewInt(1),
Data: common.FromHex(string(txData)),
})

signer := ethcoretypes.LatestSignerForChainID(big.NewInt(1))
privkey, err := crypto.GenerateKey()
Expect(err).To(BeNil())

signature, err := crypto.Sign(tx.Hash().Bytes(), privkey)
Expect(err).To(BeNil())

signedTX, err := tx.WithSignature(signer, signature)
Expect(err).To(BeNil())

serializedTX, err := signedTX.MarshalBinary()
Expect(err).To(BeNil())

ethMsg, err := core.TransactionToMessage(signedTX,
ethtypes.NewLondonSigner(signedTX.ChainId()), big.NewInt(0))
Expect(err).To(BeNil())

contractAddr = crypto.CreateAddress(ethMsg.From, signedTX.Nonce()).Hex()

proof, _ := codectypes.NewAnyWithValue(
&types.TxExecutedProof{
SerializedTX: serializedTx,
SerializedTX: serializedTX,
})
evidence = []*consensustypes.Evidence{{
ValAddress: sdk.ValAddress("validator-1"),
Expand All @@ -132,7 +183,7 @@ var _ = Describe("attest upload user smart contract", func() {
&types.UserSmartContract_Deployment{
ChainReferenceId: testChain.ChainReferenceID,
Status: types.DeploymentStatus_ACTIVE,
Address: "0x069A36eC9F812D599B558fC53b81Cc039d656153",
Address: contractAddr,
},
))
})
Expand Down
137 changes: 133 additions & 4 deletions x/evm/keeper/testdata/sample-abi.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,21 @@
"inputs": [
{
"indexed": false,
"name": "new_compass",
"name": "contract_address",
"type": "address"
},
{
"indexed": false,
"name": "payload",
"type": "bytes"
},
{
"indexed": false,
"name": "event_id",
"type": "uint256"
}
],
"name": "UpdateCompassAddressInFeeManager",
"name": "UpdateCompass",
"type": "event"
},
{
Expand Down Expand Up @@ -247,6 +252,28 @@
"name": "NodeSaleEvent",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"name": "child",
"type": "address"
},
{
"indexed": false,
"name": "deployer",
"type": "address"
},
{
"indexed": false,
"name": "event_id",
"type": "uint256"
}
],
"name": "ContractDeployed",
"type": "event"
},
{
"inputs": [
{
Expand Down Expand Up @@ -820,6 +847,20 @@
"name": "consensus",
"type": "tuple"
},
{
"components": [
{
"name": "logic_contract_address",
"type": "address"
},
{
"name": "payload",
"type": "bytes"
}
],
"name": "update_compass_args",
"type": "tuple[]"
},
{
"name": "deadline",
"type": "uint256"
Expand All @@ -829,15 +870,103 @@
"type": "uint256"
},
{
"name": "_new_compass",
"name": "relayer",
"type": "address"
}
],
"name": "compass_update_batch",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"components": [
{
"name": "validators",
"type": "address[]"
},
{
"name": "powers",
"type": "uint256[]"
},
{
"name": "valset_id",
"type": "uint256"
}
],
"name": "valset",
"type": "tuple"
},
{
"components": [
{
"name": "v",
"type": "uint256"
},
{
"name": "r",
"type": "uint256"
},
{
"name": "s",
"type": "uint256"
}
],
"name": "signatures",
"type": "tuple[]"
}
],
"name": "consensus",
"type": "tuple"
},
{
"name": "_deployer",
"type": "address"
},
{
"name": "_bytecode",
"type": "bytes"
},
{
"components": [
{
"name": "relayer_fee",
"type": "uint256"
},
{
"name": "community_fee",
"type": "uint256"
},
{
"name": "security_fee",
"type": "uint256"
},
{
"name": "fee_payer_paloma_address",
"type": "bytes32"
}
],
"name": "fee_args",
"type": "tuple"
},
{
"name": "message_id",
"type": "uint256"
},
{
"name": "deadline",
"type": "uint256"
},
{
"name": "relayer",
"type": "address"
}
],
"name": "update_compass_address_in_fee_manager",
"name": "deploy_contract",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
Expand Down
2 changes: 1 addition & 1 deletion x/evm/keeper/testdata/sample-bytecode.out

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions x/evm/keeper/testdata/user-smart-contract-tx-data.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
61baeb6300000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000300000000000000000000000008925e8676391de0c9d16158bd9993d2397b43fd000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
13 changes: 9 additions & 4 deletions x/evm/keeper/user_smart_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,20 @@ func (k Keeper) CreateUserSmartContractDeployment(
bytecode := slices.Concat(common.FromHex(contract.Bytecode),
common.FromHex(contract.ConstructorInput))

senderAddr, err := sdk.ValAddressFromBech32(addr)
if err != nil {
return 0, err
}

sdkCtx := sdk.UnwrapSDKContext(ctx)
userSmartContract := &types.UploadUserSmartContract{
Bytecode: bytecode,
DeployerAddress: chainInfo.SmartContractDeployerAddr,
// 10 minute deadline, same as SLCs
Deadline: sdkCtx.BlockTime().Add(10 * time.Minute).Unix(),
Author: addr,
BlockHeight: blockHeight,
Id: id,
Deadline: sdkCtx.BlockTime().Add(10 * time.Minute).Unix(),
SenderAddress: senderAddr,
BlockHeight: blockHeight,
Id: id,
}

return k.AddUploadUserSmartContractToConsensus(ctx, targetChain, userSmartContract)
Expand Down
Loading

0 comments on commit fd7a594

Please sign in to comment.