Skip to content
This repository has been archived by the owner on Mar 24, 2023. It is now read-only.

Commit

Permalink
Merge pull request #61 from RetricSu/fix-malicious-mapping
Browse files Browse the repository at this point in the history
Fix malicious mapping
  • Loading branch information
RetricSu authored Sep 7, 2021
2 parents 4df2892 + f5dd932 commit d3baa8c
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 26 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@
"eslint": "^7.16.0",
"prettier": "^2.2.1"
},
"version": "0.6.0-rc6",
"version": "0.6.0-rc7",
"author": "hupeng <bitrocks.hu@gmail.com>"
}
6 changes: 3 additions & 3 deletions packages/api-server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@godwoken-web3/api-server",
"version": "0.6.0-rc6",
"version": "0.6.0-rc7",
"private": true,
"scripts": {
"start": "concurrently \"tsc -w\" \"DEBUG=godwoken-web3-api:server nodemon ./bin/www\"",
Expand All @@ -16,9 +16,9 @@
},
"dependencies": {
"@ckb-lumos/base": "^0.16.0",
"@godwoken-web3/godwoken": "0.6.0-rc6",
"@godwoken-web3/godwoken": "0.6.0-rc7",
"@newrelic/native-metrics": "^7.0.1",
"@polyjuice-provider/base": "^0.0.1-rc7",
"@polyjuice-provider/base": "^0.0.1-rc10",
"@sentry/node": "^6.11.0",
"blake2b": "2.1.3",
"ckb-js-toolkit": "^0.10.2",
Expand Down
13 changes: 13 additions & 0 deletions packages/api-server/src/base/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,16 @@ export function isAddressMatch(
const computedShortAddress = ethAddressToShortAddress(ethAddress);
return shortAddress === computedShortAddress;
}

export async function isShortAddressOnChain(
godwokenClient: GodwokenClient,
shortAddress: HexString
) {
const scriptHash = await godwokenClient.getScriptHashByShortAddress(
shortAddress
);
if (scriptHash == null) {
return false;
}
return true;
}
5 changes: 2 additions & 3 deletions packages/api-server/src/db/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@ export class AccountsQuery {
shortAddress: HexString
): Promise<boolean> {
const result = await this.knex<DbAccount>(ACCOUNTS_TABLE_NAME)
.where("eth_address", ethAddress)
.orWhere("gw_short_address", shortAddress)
.where("eth_address", toBuffer(ethAddress))
.orWhere("gw_short_address", toBuffer(shortAddress))
.first();

return result != null;
}

Expand Down
13 changes: 9 additions & 4 deletions packages/api-server/src/methods/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
EthTransactionReceipt,
} from "../../base/types/api";
import { filterWeb3Transaction } from "../../filter-web3-tx";
import { Abi } from "@polyjuice-provider/base";
import { Abi, ShortAddress, ShortAddressType } from "@polyjuice-provider/base";
import { SUDT_ERC20_PROXY_ABI, allowedAddresses } from "../../erc20";
import { FilterManager } from "../../cache";
import { toHex } from "../../util";
Expand Down Expand Up @@ -1078,9 +1078,14 @@ async function ethCallTx(
}

const abi = new Abi(SUDT_ERC20_PROXY_ABI);
const ethToGwAddr = async (addr: HexString): Promise<HexString> => {

// TODO: save addressMapping into db when encounter not-exist-eth-eoa-address
const ethToGwAddr = async (addr: HexString): Promise<ShortAddress> => {
const result = await allTypeEthAddressToShortAddress(rpc, addr);
return result!;
return {
value: result!,
type: ShortAddressType.eoaAddress, // TODO: return correct address type
};
};

// TODO: find by db.addresses when not found
Expand Down Expand Up @@ -1114,7 +1119,7 @@ async function ethCallTx(
blockNumber
);

const abiItem = abi.get_intereted_abi_item_by_encoded_data(data);
const abiItem = abi.get_interested_abi_item_by_encoded_data(data);

if (abiItem && isEthWallet) {
const returnDataWithShortAddress =
Expand Down
178 changes: 173 additions & 5 deletions packages/api-server/src/methods/modules/poly.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
import { middleware, validators } from "../validator";
import { Hash, HexNumber, Address } from "@ckb-lumos/base";
import { Hash, HexNumber, Address, HexString } from "@ckb-lumos/base";
import { toHexNumber } from "../../base/types/uint";
import { envConfig } from "../../base/env-config";
import { InternalError, InvalidParamsError, Web3Error } from "../error";
import {
InternalError,
InvalidParamsError,
RpcError,
Web3Error,
} from "../error";
import { Query } from "../../db";
import { isAddressMatch } from "../../base/address";
import { isAddressMatch, isShortAddressOnChain } from "../../base/address";
import { GW_RPC_REQUEST_ERROR } from "../error-code";
import {
decodeArgs,
deserializeL2TransactionWithAddressMapping,
deserializeRawL2TransactionWithAddressMapping,
deserializeAbiItem,
getAddressesFromInputDataByAbi,
EMPTY_ABI_ITEM_SERIALIZE_STR,
} from "@polyjuice-provider/base";
import { AbiItem } from "@polyjuice-provider/godwoken/lib/abiTypes";
import {
L2TransactionWithAddressMapping,
RawL2TransactionWithAddressMapping,
} from "@polyjuice-provider/godwoken/lib/addressTypes";
import { GodwokenClient } from "@godwoken-web3/godwoken";

export class Poly {
private query: Query;
private rpc: GodwokenClient;

constructor() {
this.query = new Query(envConfig.databaseUrl);
this.rpc = new GodwokenClient(envConfig.godwokenJsonRpc);

this.getEthAddressByGodwokenShortAddress = middleware(
this.getEthAddressByGodwokenShortAddress.bind(this),
Expand Down Expand Up @@ -50,14 +72,48 @@ export class Poly {
}
}

async submitL2Transaction(args: any[]) {
try {
const data = args[0];
const txWithAddressMapping: L2TransactionWithAddressMapping =
deserializeL2TransactionWithAddressMapping(data);
const l2Tx = txWithAddressMapping.tx;
const result = await this.rpc.submitL2Transaction(l2Tx);
// if result is fine, then tx is legal, we can start thinking to store the address mapping
await saveAddressMapping(this.query, this.rpc, txWithAddressMapping);
return result;
} catch (error) {
parseError(error);
}
}

async executeRawL2Transaction(args: any[]) {
try {
const data = args[0];
const txWithAddressMapping: RawL2TransactionWithAddressMapping =
deserializeRawL2TransactionWithAddressMapping(data);
const rawL2Tx = txWithAddressMapping.raw_tx;
const result = await this.rpc.executeRawL2Transaction(rawL2Tx);
// if result is fine, then tx is legal, we can start thinking to store the address mapping
await saveAddressMapping(this.query, this.rpc, txWithAddressMapping);
return result;
} catch (error) {
parseError(error);
}
}

async saveEthAddressGodwokenShortAddressMapping(
args: [string, string]
): Promise<string> {
// TODO: remove this function later
// throw new Web3Error(
// "this method is deprecated! please upgrade @polyjuice-provider over 0.0.1-rc10 version! see: https://www.npmjs.com/org/polyjuice-provider"
// );
try {
const ethAddress = args[0];
const godwokenShortAddress = args[1];
// todo: save before check if it not exsit;
// TODO: check exists

// check if it exist
const exists = await this.query.accounts.exists(
ethAddress,
godwokenShortAddress
Expand Down Expand Up @@ -142,3 +198,115 @@ export class Poly {
}
}
}

async function saveAddressMapping(
query: Query,
rpc: GodwokenClient,
txWithAddressMapping:
| L2TransactionWithAddressMapping
| RawL2TransactionWithAddressMapping
) {
console.log(JSON.stringify(txWithAddressMapping, null, 2));

if (
txWithAddressMapping.addresses.length === "0x0" ||
txWithAddressMapping.addresses.data.length === 0
) {
console.log(`empty addressMapping, abort saving.`);
return;
}

if (txWithAddressMapping.extra === EMPTY_ABI_ITEM_SERIALIZE_STR) {
console.log(`addressMapping without abiItem, abort saving.`);
return;
}

let rawTx;
if ("raw_tx" in txWithAddressMapping) {
rawTx = txWithAddressMapping.raw_tx;
} else {
rawTx = txWithAddressMapping.tx.raw;
}
const ethTxData = decodeArgs(rawTx.args).data;
const abiItemStr = txWithAddressMapping.extra;
const abiItem: AbiItem = deserializeAbiItem(abiItemStr);
const addressesFromEthTxData = getAddressesFromInputDataByAbi(
ethTxData,
abiItem
);
if (addressesFromEthTxData.length === 0) {
console.log(
`eth tx data ${ethTxData} contains no valid address, abort saving.`
);
return;
}

await Promise.all(
txWithAddressMapping.addresses.data.map(async (item) => {
const ethAddress: HexString = item.eth_address;
const godwokenShortAddress: HexString = item.gw_short_address;

if (!addressesFromEthTxData.includes(godwokenShortAddress)) {
console.log(
`illegal address mapping, since godwoken_short_address ${godwokenShortAddress} is not in the ethTxData. expected addresses: ${JSON.stringify(
addressesFromEthTxData,
null,
2
)}`
);
return;
}

try {
const exists = await query.accounts.exists(
ethAddress,
godwokenShortAddress
);
if (exists) {
console.log(
`abort saving, since godwoken_short_address ${godwokenShortAddress} is already saved on database.`
);
return;
}
if (!isAddressMatch(ethAddress, godwokenShortAddress)) {
throw new Error(
`eth_address ${ethAddress} and godwoken_short_address ${godwokenShortAddress} unmatched! abort saving!`
);
}
const isExistOnChain = await isShortAddressOnChain(
rpc,
godwokenShortAddress
);
if (isExistOnChain) {
console.log(
`abort saving, since godwoken_short_address ${godwokenShortAddress} is already on chain.`
);
return;
}

await query.accounts.save(ethAddress, godwokenShortAddress);
console.log(
`poly_save: insert one record, [${godwokenShortAddress}]: ${ethAddress}`
);
return;
} catch (error) {
console.log(
`abort saving addressMapping [${godwokenShortAddress}]: ${ethAddress} , will keep saving the rest. =>`,
error
);
}
})
);
}

function parseError(error: any): void {
const prefix = "JSONRPCError: server error ";
let message: string = error.message;
if (message.startsWith(prefix)) {
const jsonErr = message.slice(prefix.length);
const err = JSON.parse(jsonErr);
throw new RpcError(err.code, err.message);
}

throw new RpcError(GW_RPC_REQUEST_ERROR, error.message);
}
2 changes: 1 addition & 1 deletion packages/godwoken/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@godwoken-web3/godwoken",
"version": "0.6.0-rc6",
"version": "0.6.0-rc7",
"private": true,
"main": "lib/index.js",
"scripts": {
Expand Down
18 changes: 9 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,13 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"

"@polyjuice-provider/base@^0.0.1-rc7":
version "0.0.1-rc7"
resolved "https://registry.yarnpkg.com/@polyjuice-provider/base/-/base-0.0.1-rc7.tgz#5df16cccc178f049192139758ecd7852e4529480"
integrity sha512-wFwDBf2xpDBySAjBKI0A1ugfJ8398MW+LiLPQiJoY1Ca1e85+I6OMYCjQGGGYB2gbALWKwAcplin7RVbGiajPA==
"@polyjuice-provider/base@^0.0.1-rc10":
version "0.0.1-rc10"
resolved "https://registry.yarnpkg.com/@polyjuice-provider/base/-/base-0.0.1-rc10.tgz#23e8c74993eaaaa18a391a103e18f1aedcc369f4"
integrity sha512-2cGKXh2ST57qMlthL8tKVv5/JM+RtrJnIjifD1Sx7zWpKuFa+m6MWjwK+LUNWJzO3/6NKjhotIEMOqr3jI++HQ==
dependencies:
"@ckb-lumos/base" "^0.16.0"
"@polyjuice-provider/godwoken" "^0.0.1-rc7"
"@polyjuice-provider/godwoken" "^0.0.1-rc10"
buffer "^6.0.3"
encoding "^0.1.13"
eth-sig-util "^3.0.1"
Expand All @@ -342,10 +342,10 @@
web3 "^1.3.4"
xhr2-cookies "^1.1.0"

"@polyjuice-provider/godwoken@^0.0.1-rc7":
version "0.0.1-rc7"
resolved "https://registry.yarnpkg.com/@polyjuice-provider/godwoken/-/godwoken-0.0.1-rc7.tgz#1c7ff81d92061adbbd1da51721d1545d20e4a2a1"
integrity sha512-jBQ1Ivf1TbcX935bUh+QPWwCdueQEsEmLzU6gU3/luTVNwBHHrNElwMDtoqrTVi0akA9CRMWoNMKzSTjNnTNNw==
"@polyjuice-provider/godwoken@^0.0.1-rc10":
version "0.0.1-rc10"
resolved "https://registry.yarnpkg.com/@polyjuice-provider/godwoken/-/godwoken-0.0.1-rc10.tgz#ca927aac16d80046440b278cdba7f08b85c5c832"
integrity sha512-8Em+jlKqaoDqFM3Ab+fax3dV6gZbMB0oAdsHgxyuiP0XmNBccZRA1PnHwgTzB1hcauqAz4J9IbO92tDY717Vfg==
dependencies:
"@ckb-lumos/base" "^0.16.0"
ckb-js-toolkit "^0.9.3"
Expand Down

0 comments on commit d3baa8c

Please sign in to comment.