Skip to content
This repository has been archived by the owner on Apr 8, 2024. It is now read-only.

Commit

Permalink
[PI-139]: Add ledger support
Browse files Browse the repository at this point in the history
  • Loading branch information
arijoon committed Aug 3, 2023
1 parent 78b76c8 commit b4b8835
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 28 deletions.
3 changes: 1 addition & 2 deletions examples/33.generateL1RegistrationPayload.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,10 @@ const rhinofiConfig = {
const { starkKeyHex, ethAddress } = await rhinofi.getUserConfig()

const l1RegistrationSignature = await rhinofi.stark.signRegistration(
starkPrivKey,
ethAddress
)

const callData = rhinofi.stark.l1RegistrationCallData(
const callData = await rhinofi.stark.l1RegistrationCallData(
starkKeyHex,
ethAddress,
l1RegistrationSignature
Expand Down
5 changes: 4 additions & 1 deletion src/lib/keystore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ module.exports = sw => starkPrivateKey => {
const sign = async tx => {
const starkKeyPair = await getKeyPair()

const starkMessage = getMessage(sw)(tx)
const starkMessage = typeof tx === 'string'
? tx
: getMessage(sw)(tx)

const signature = FP.mapValues(
x => '0x' + x,
starkSign({ sw }, starkKeyPair, starkMessage)
Expand Down
33 changes: 26 additions & 7 deletions src/lib/ledger/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,36 @@ const getMessage = sw => tx => {
return starkTransferTxToMessageHash(sw)(tx)
}

const withTransport = (dvf) => async (fn) => {
const Transport = selectTransport(dvf.isBrowser)
const transport = await Transport.create()
try {
return await fn(transport)
} finally {
await transport.close()
}
}

const getTxSignature = async (dvf, tx, path) => {
// Generic stark message Signing
if (typeof tx === 'string') {
return withTransport(dvf)(async (transport) => {
const eth = new Eth(transport)
const { address } = await eth.getAddress(path)
const starkPath = dvf.stark.ledger.getPath(address)
const paddedMessage = `0x${tx.padEnd(64, '0').substr(-64)}`
return eth.starkUnsafeSign(
starkPath,
paddedMessage
)
})
}

if (tx.type != null) {
if (!(transferTransactionTypes.includes(tx.type))) {
throw new DVFError(`Unsupported stark transaction type: ${tx.type}`, { tx })
}
let transport
try {
const Transport = selectTransport(dvf.isBrowser)
transport = await Transport.create()
return withTransport(dvf)(async (transport) => {
const eth = new Eth(transport)
const { address } = await eth.getAddress(path)
const starkPath = dvf.stark.ledger.getPath(address)
Expand Down Expand Up @@ -81,9 +102,7 @@ const getTxSignature = async (dvf, tx, path) => {
tx.type === 'ConditionalTransferRequest' ? tx.factRegistryAddress : null,
tx.type === 'ConditionalTransferRequest' ? tx.fact : null
)
} finally {
await transport.close()
}
})
} else {
const { starkSignature } = await createSignedOrder(
dvf, path, tx, { returnStarkPublicKey: false }
Expand Down
3 changes: 1 addition & 2 deletions src/lib/stark/createRegistrationMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ const EC_ORDER = utils.BN('36185027886661312136973227830950701055267437517160874
* ethAddress: string) => utils.BN}
*/
module.exports = (dvf, starkHex, ethAddress) => {
const starkware = dvf.sw || sw
if (!ethAddress) {
throw new Error('ethAddress is required')
}

if (!starkHex) {
throw new Error('ethAddress is required')
throw new Error('starkKeyHex is required')
}

/*
Expand Down
22 changes: 6 additions & 16 deletions src/lib/stark/signRegistration.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,29 @@ const DVFError = require('../dvf/DVFError')
const sw = require('@rhino.fi/starkware-crypto')

const pad = (rec) => rec.padStart(64, 0)
const removePrefix = (input) => input.replace(/^0x/, '')

/**
* @type {(dvf: ReturnType<import('../dvf/bindApi')>,
* tradingKey: string,
* ethAddress: string) => Promise<string>}
*/
module.exports = async (dvf, tradingKey, ethAddress) => {
const starkware = dvf.sw || sw
if (!tradingKey) {
throw new Error('tradingKey is required')
}

/*
uint256 msgHash = uint256(
keccak256(abi.encodePacked("UserRegistration:", ethKey, starkKey))
) % ECDSA.EC_ORDER;
*/

module.exports = async (dvf, ethAddress) => {
const { dvfStarkProvider } = dvf
const publicKey = await dvfStarkProvider.getPublicKey()

const message = dvf.stark.createRegistrationMessage(`0x${pad(publicKey.x)}`, ethAddress)

try {
const { starkKeyPair } = dvf.stark.createKeyPair(tradingKey)

const { r, s } = starkware.sign(starkKeyPair, message)
const { r, s } = await dvfStarkProvider.sign(message)

const components = [
r.toString(16),
s.toString(16),
publicKey.y
].map(pad)
]
.map(removePrefix)
.map(pad)

const final = `0x${components.join('')}`

Expand Down

0 comments on commit b4b8835

Please sign in to comment.