Invocation Path

  1. Dapp request personal_sign1

    const msg = `0x${Buffer.from(exampleMessage, 'utf8').toString('hex')}`
    console.log({ msg })
    const networkId = networkDiv.innerHTML
    const extraParams = { networkId }
    const sign = await window.starcoin.request({
      method: 'personal_sign',
      // params: [msg, from, 'Example password'],
      // extraParams = params[2] || {}; means it should be an object:
      // params: [msg, from, { pwd: 'Example password' }],
      params: [msg, from, extraParams],
    })
    
  2. Starmask handling request signPersonalMessage

Conclusion

Message signed at keyring:

/**
 * Sign Personal Message
 *
 * Attempts to sign the provided message paramaters.
 * Prefixes the hash before signing per the personal sign expectation.
 *
 * @param {Object} msgParams - The message parameters to sign.
 * @returns {Promise<Buffer>} The raw signature.
 */
signPersonalMessage(msgParams, opts = {}) {
  const address = normalizeAddress(msgParams.from)
  return this.getKeyringForAccount(address)
    .then((keyring) => {
      return keyring.signPersonalMessage(address, msgParams.rawData, opts)
    })
}

The rawData is built at2:

const rawData = Buffer.from(stripHexPrefix(cleanMsgParams.data), 'hex').toString('utf8')

Then the getEd25519SignMsgBytes will be invoked:

export function getEd25519SignMsgBytes(
  signingMessage: SigningMessage,
): bytes {
  const hasher = createSigningMessageHasher();
  const hashSeedBytes = hasher.get_salt();

  const signingMessageBytes = (function () {
    const se = new BcsSerializer();
    signingMessage.serialize(se);
    return se.getBytes();
  })();

  const msgBytes = ((a, b) => {
    const tmp = new Uint8Array(a.length + b.length);
    tmp.set(a, 0);
    tmp.set(b, a.length);
    return tmp;
  })(hashSeedBytes, signingMessageBytes);

  return msgBytes;
}

The msgBytes is the combination of hashSeedBytes and message itself.