New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

gridplus-sdk

Package Overview
Dependencies
Maintainers
1
Versions
182
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gridplus-sdk - npm Package Compare versions

Comparing version 0.7.27 to 0.8.0

6

package.json
{
"name": "gridplus-sdk",
"version": "0.7.27",
"version": "0.8.0",
"description": "SDK to interact with GridPlus Lattice1 device",

@@ -34,3 +34,3 @@ "scripts": {

"elliptic": "6.5.4",
"ethers": "^5.0.31",
"ethers": "^5.4.2",
"ethers-eip712": "^0.2.0",

@@ -55,3 +55,3 @@ "js-sha3": "^0.8.0",

"eslint-plugin-standard": "^4.0.0",
"ethereumjs-tx": "^2.1.2",
"ethereumjs-util": "^7.1.0",
"it-each": "^0.4.0",

@@ -58,0 +58,0 @@ "lodash": ">=4.17.21",

@@ -745,3 +745,3 @@ const bitwise = require('bitwise');

// Determine the `v` param and add it to the sig before returning
const rawTx = ethereum.buildEthRawTx(req, sig, ethAddr, req.useEIP155);
const rawTx = ethereum.buildEthRawTx(req, sig, ethAddr);
returnData.data = {

@@ -748,0 +748,0 @@ tx: `0x${rawTx}`,

@@ -276,2 +276,41 @@ // Consistent with Lattice's IV

const legacy = (v.length === 0);
// BASE FIELDS
//--------------------------------------
// Various size constants have changed on the firmware side over time and
// are captured here
if (!legacy && gte(v, [0, 10, 4])) {
// >=0.10.3
c.reqMaxDataSz = 1678;
c.ethMaxGasPrice = 20000000000000; // 20000 gwei
c.addrFlagsAllowed = true;
} else if (!legacy && gte(v, [0, 10, 0])) {
// >=0.10.0
c.reqMaxDataSz = 1678;
c.ethMaxGasPrice = 20000000000000; // 20000 gwei
c.addrFlagsAllowed = true;
} else {
// Legacy or <0.10.0
c.reqMaxDataSz = 1152;
c.ethMaxGasPrice = 500000000000; // 500 gwei
c.addrFlagsAllowed = false;
}
// These transformations apply to all versions
c.ethMaxDataSz = c.reqMaxDataSz - 128;
c.ethMaxMsgSz = c.ethMaxDataSz;
// EXTRA FIELDS ADDED IN LATER VERSIONS
//-------------------------------------
// V0.10.12 allows new ETH transaction types
if (!legacy && gte(v, [0, 11, 0])) {
c.allowedEthTxTypesVersion = 1;
c.allowedEthTxTypes = [
1, // eip2930
2, // eip1559
]
c.totalExtraEthTxDataSz = 10;
}
// V0.10.10 allows a user to sign a prehashed ETH message if payload too big

@@ -299,26 +338,3 @@ if (!legacy && gte(v, [0, 10, 10])) {

}
// Various size constants have changed on the firmware side over time and
// are captured here
if (!legacy && gte(v, [0, 10, 4])) {
// >=0.10.3
c.reqMaxDataSz = 1678;
c.ethMaxDataSz = c.reqMaxDataSz - 128;
c.ethMaxMsgSz = c.ethMaxDataSz;
c.ethMaxGasPrice = 20000000000000; // 20000 gwei
c.addrFlagsAllowed = true;
} else if (!legacy && gte(v, [0, 10, 0])) {
// >=0.10.0
c.reqMaxDataSz = 1678;
c.ethMaxDataSz = c.reqMaxDataSz - 128;
c.ethMaxMsgSz = c.ethMaxDataSz;
c.ethMaxGasPrice = 20000000000000; // 20000 gwei
c.addrFlagsAllowed = true;
} else {
// Legacy or <0.10.0
c.reqMaxDataSz = 1152;
c.ethMaxDataSz = c.reqMaxDataSz - 128;
c.ethMaxMsgSz = c.ethMaxDataSz;
c.ethMaxGasPrice = 500000000000; // 500 gwei
c.addrFlagsAllowed = false;
}
return c;

@@ -325,0 +341,0 @@ }

@@ -49,3 +49,3 @@ // Utils for Ethereum transactions. This is effecitvely a shim of ethereumjs-util, which

Buffer.from(keccak256(Buffer.concat([get_personal_sign_prefix(msg.length), msg])), 'hex');
return addRecoveryParam(hash, sig, signer, 1, false)
return addRecoveryParam(hash, sig, signer, { chainId: 1, useEIP155: false })
} else if (input.protocol === 'eip712') {

@@ -62,6 +62,6 @@ const digest = prehash ? prehash : eip712.TypedDataUtils.encodeDigest(req.input.payload);

let { chainId=1 } = data;
const { signerPath, eip155=null, fwConstants } = data;
const { signerPath, eip155=null, fwConstants, type=null } = data;
const { extraDataFrameSz, extraDataMaxFrames, prehashAllowed } = fwConstants;
const EXTRA_DATA_ALLOWED = extraDataFrameSz > 0 && extraDataMaxFrames > 0;
const MAX_BASE_DATA_SZ = fwConstants.ethMaxDataSz;
let MAX_BASE_DATA_SZ = fwConstants.ethMaxDataSz;
const VAR_PATH_SZ = fwConstants.varAddrPathSzAllowed;

@@ -80,3 +80,12 @@

throw new Error('`signerPath` not provided');
// We support eip1559 and eip2930 types (as well as legacy)
const eip1559IsAllowed = (fwConstants.allowedEthTxTypes &&
fwConstants.allowedEthTxTypes.indexOf(2) > -1);
const eip2930IsAllowed = (fwConstants.allowedEthTxTypes &&
fwConstants.allowedEthTxTypes.indexOf(1) > -1);
const isEip1559 = (eip1559IsAllowed && (type === 2 || type === 'eip1559'));
const isEip2930 = (eip2930IsAllowed && (type === 1 || type === 'eip2930'));
if (type !== null && !isEip1559 && !isEip2930)
throw new Error('Unsupported Ethereum transaction type');
// Determine if we should use EIP155 given the chainID.

@@ -87,4 +96,8 @@ // If we are explicitly told to use eip155, we will use it. Otherwise,

let useEIP155 = chainUsesEIP155(chainId);
if (eip155 !== null && typeof eip155 === 'boolean')
if (eip155 !== null && typeof eip155 === 'boolean') {
useEIP155 = eip155;
} else if (isEip1559 || isEip2930) {
// Newer transaction types do not use EIP155 since the chainId is serialized
useEIP155 = false;
}

@@ -102,4 +115,5 @@ // Hack for metamask, which sends value=null for 0 ETH transactions

// Build the transaction buffer array
const chainIdBytes = ensureHexBuffer(chainId);
const nonceBytes = ensureHexBuffer(data.nonce);
const gasPriceBytes = ensureHexBuffer(data.gasPrice);
let gasPriceBytes;
const gasLimitBytes = ensureHexBuffer(data.gasLimit);

@@ -109,4 +123,28 @@ const toBytes = ensureHexBuffer(data.to);

const dataBytes = ensureHexBuffer(data.data);
if (isEip1559 || isEip2930) {
// EIP1559 and EIP2930 transactions have a chainID field
rawTx.push(chainIdBytes);
}
rawTx.push(nonceBytes);
rawTx.push(gasPriceBytes);
let maxPriorityFeePerGasBytes, maxFeePerGasBytes;
if (isEip1559) {
if (!data.maxPriorityFeePerGas)
throw new Error('EIP1559 transactions must include `maxPriorityFeePerGas`');
if (!data.maxPriorityFeePerGas)
throw new Error('EIP1559 transactions must include `maxFeePerGas`');
maxPriorityFeePerGasBytes = ensureHexBuffer(data.maxPriorityFeePerGas);
rawTx.push(maxPriorityFeePerGasBytes);
maxFeePerGasBytes = ensureHexBuffer(data.maxFeePerGas);
rawTx.push(maxFeePerGasBytes);
// EIP1559 renamed "gasPrice" to "maxFeePerGas", but firmware still
// uses `gasPrice` in the struct, so update that value here.
gasPriceBytes = maxFeePerGasBytes;
if (0 > Buffer.compare(maxFeePerGasBytes, maxPriorityFeePerGasBytes))
throw new Error('EIP1559 requirement not met: (maxFeePerGasBytes > maxPriorityFeePerGasBytes)')
} else {
// EIP1559 transactions do not have the gasPrice field
gasPriceBytes = ensureHexBuffer(data.gasPrice);
rawTx.push(gasPriceBytes);
}
rawTx.push(gasLimitBytes);

@@ -116,5 +154,21 @@ rawTx.push(toBytes);

rawTx.push(dataBytes);
// Add empty v,r,s values
if (useEIP155 === true) {
rawTx.push(ensureHexBuffer(chainId)); // v
// We do not currently support accessList in firmware so we need to prehash if
// the list is non-null
let PREHASH_FROM_ACCESS_LIST = false;
if (isEip1559 || isEip2930) {
const accessList = [];
if (Array.isArray(data.accessList)) {
data.accessList.forEach((listItem) => {
const keys = [];
listItem.storageKeys.forEach((key) => {
keys.push(ensureHexBuffer(key))
})
accessList.push([ ensureHexBuffer(listItem.address), keys ])
PREHASH_FROM_ACCESS_LIST = true;
})
}
rawTx.push(accessList);
} else if (useEIP155 === true) {
// Add empty v,r,s values for EIP155 legacy transactions
rawTx.push(chainIdBytes); // v (which is the same as chainId in EIP155 txs)
rawTx.push(ensureHexBuffer(null)); // r

@@ -127,2 +181,9 @@ rawTx.push(ensureHexBuffer(null)); // s

const ETH_TX_NON_DATA_SZ = 122; // Accounts for metadata and non-data params
let ETH_TX_EXTRA_FIELDS_SZ = 0; // Accounts for newer ETH tx types (e.g. eip1559)
if (fwConstants.allowedEthTxTypesVersion === 1) {
// eip1559 and eip2930
// Add extra params and shrink the data region (extraData blocks are unaffected)
ETH_TX_EXTRA_FIELDS_SZ = fwConstants.totalExtraEthTxDataSz;
MAX_BASE_DATA_SZ -= ETH_TX_EXTRA_FIELDS_SZ;
}
const txReqPayload = Buffer.alloc(MAX_BASE_DATA_SZ + ETH_TX_NON_DATA_SZ);

@@ -152,3 +213,2 @@ let off = 0;

}
// 2. Signer Path

@@ -177,2 +237,26 @@ //------------------

valueBytes.copy(txReqPayload, off + (32 - valueBytes.length)); off += 32;
// Extra Tx data comes before `data` in the struct
let PREHASH_UNSUPPORTED = false;
if (fwConstants.allowedEthTxTypesVersion === 1) {
const extraEthTxDataSz = fwConstants.totalExtraEthTxDataSz || 0;
// Some types may not be supported by firmware, so we will need to prehash
if (PREHASH_FROM_ACCESS_LIST) {
PREHASH_UNSUPPORTED = true;
}
txReqPayload.writeUint8(PREHASH_UNSUPPORTED === true, off); off += 1;
// EIP1559 & EIP2930 struct version
if (isEip1559) {
txReqPayload.writeUint8(2, off); off += 1; // Eip1559 type enum value
if (maxPriorityFeePerGasBytes.length > 8)
throw new Error('maxPriorityFeePerGasBytes too large');
maxPriorityFeePerGasBytes.copy(txReqPayload, off + (8 - maxPriorityFeePerGasBytes.length)); off += 8;
} else if (isEip2930) {
txReqPayload.writeUint8(1, off); off += 1; // Eip2930 type enum value
off += extraEthTxDataSz - 2; // Skip EIP1559 params
} else {
off += extraEthTxDataSz - 1; // Skip EIP1559 and EIP2930 params
}
}
// Flow data into extraData requests, which will follow-up transaction requests, if supported/applicable

@@ -196,6 +280,5 @@ const extraDataPayloads = [];

}
if (prehashAllowed && totalSz > maxSzAllowed) {
// If this payload is too large to send, but the Lattice allows a prehashed message, do that
prehash = Buffer.from(keccak256(rlp.encode(rawTx)), 'hex')
prehash = Buffer.from(keccak256(get_rlp_encoded_preimage(rawTx, type)), 'hex')
} else {

@@ -212,3 +295,8 @@ if ((!EXTRA_DATA_ALLOWED) || (EXTRA_DATA_ALLOWED && totalSz > maxSzAllowed))

}
} else if (PREHASH_UNSUPPORTED) {
// If something is unsupported in firmware but we want to allow such transactions,
// we prehash the message here.
prehash = Buffer.from(keccak256(get_rlp_encoded_preimage(rawTx, type)), 'hex')
}
// Write the data size (does *NOT* include the chainId buffer, if that exists)

@@ -230,2 +318,3 @@ txReqPayload.writeUInt16BE(dataBytes.length, off); off += 2;

rawTx,
type,
payload: txReqPayload.slice(0, off),

@@ -255,9 +344,9 @@ extraDataPayloads,

// and attah the full signature to the end of the transaction payload
exports.buildEthRawTx = function(tx, sig, address, useEIP155=true) {
exports.buildEthRawTx = function(tx, sig, address) {
// RLP-encode the data we sent to the lattice
const rlpEncoded = rlp.encode(tx.rawTx);
const hash = Buffer.from(keccak256(rlpEncoded), 'hex')
const newSig = addRecoveryParam(hash, sig, address, tx.chainId, useEIP155);
const hash = Buffer.from(keccak256(get_rlp_encoded_preimage(tx.rawTx, tx.type)), 'hex');
const newSig = addRecoveryParam(hash, sig, address, tx);
// Use the signature to generate a new raw transaction payload
const newRawTx = tx.rawTx.slice(0, 6);
// Strip the last 3 items and replace them with signature components
const newRawTx = tx.useEIP155 ? tx.rawTx.slice(0, -3) : tx.rawTx;
newRawTx.push(newSig.v);

@@ -268,7 +357,11 @@ // Per `ethereumjs-tx`, RLP encoding should include signature components w/ stripped zeros

newRawTx.push(stripZeros(newSig.s));
return rlp.encode(newRawTx).toString('hex');
let rlpEncodedWithSig = rlp.encode(newRawTx);
if (tx.type) {
rlpEncodedWithSig = Buffer.concat([Buffer.from([tx.type]), rlpEncodedWithSig])
}
return rlpEncodedWithSig.toString('hex');
}
// Attach a recovery parameter to a signature by brute-forcing ECRecover
function addRecoveryParam(hashBuf, sig, address, chainId, useEIP155) {
function addRecoveryParam(hashBuf, sig, address, txData={}) {
try {

@@ -286,3 +379,3 @@ // Rebuild the keccak256 hash here so we can `ecrecover`

if (pubToAddrStr(pubkey) === address.toString('hex')) {
sig.v = getRecoveryParam(v, useEIP155, chainId);
sig.v = getRecoveryParam(v, txData);
return sig;

@@ -294,3 +387,3 @@ }

if (pubToAddrStr(pubkey) === address.toString('hex')) {
sig.v = getRecoveryParam(v, useEIP155, chainId);
sig.v = getRecoveryParam(v, txData);
return sig;

@@ -328,6 +421,15 @@ } else {

// * For EIP155 transactions, return `(CHAIN_ID*2) + 35 + v`
function getRecoveryParam(v, useEIP155, chainId=null) {
function getRecoveryParam(v, txData={}) {
const { chainId, useEIP155, type } = txData;
// For EIP1559 and EIP2930 transactions, we want the recoveryParam (0 or 1)
// rather than the `v` value because the `chainId` is already included in the
// transaction payload.
if (type === 1 || type === 2) {
return ensureHexBuffer(v, true); // 0 or 1, with 0 expected as an empty buffer
}
// If we are not using EIP155, convert v directly to a buffer and return it
if (false === useEIP155 || chainId === null)
return Buffer.from(new BN(v).plus(27).toString(16), 'hex');
// We will use EIP155 in most cases. Convert v to a bignum and operate on it.

@@ -724,2 +826,10 @@ // Note that the protocol calls for v = (CHAIN_ID*2) + 35/36, where 35 or 36

);
}
function get_rlp_encoded_preimage(rawTx, txType) {
if (txType) {
return Buffer.concat([Buffer.from([txType]), rlp.encode(rawTx)]);
} else {
return rlp.encode(rawTx);
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc