another adversarial review's fixes

This commit is contained in:
Alain Brenzikofer
2026-08-31 08:10:19 +02:00
parent 52afb09711
commit 3de738e9bf
9 changed files with 162 additions and 15 deletions
+1 -1
View File
@@ -858,7 +858,7 @@ data ChatResponse
| CRNameQuote {user :: User, nameLabel :: Text, nameAvailable :: Bool, nameReserved :: Bool, namePriceUsdCents :: Word32, nameYears :: Word32}
| CRNameCode {user :: User, codeMinLength :: Int, nameYears :: Word32, codeExpires :: UTCTime}
| CRNames {user :: User, namesOwned :: [(Text, Text, UTCTime, Word32)]}
| CRNameInfo {user :: User, regName :: Text, regOwner :: Text, regPath :: Text, nameContact :: [Text], nameChannel :: [Text], regExpiry :: UTCTime, nameEditsLeft :: Word32}
| CRNameInfo {user :: User, regName :: Text, regOwner :: Text, regOwnerIsOurs :: Bool, regPath :: Text, nameContact :: [Text], nameChannel :: [Text], regExpiry :: UTCTime, nameEditsLeft :: Word32}
| CRNameLinkSet {user :: User, regName :: Text, nameRecord :: Text, regTxHash :: TxHash}
| CRNameRescan {user :: User, namesFound :: [(Text, Text)]}
| CRNameKeys {user :: User, walletKeys :: [(Int, [(Maybe AccountIndex, [(Maybe NameIndex, Text, Text)])], Bool, Bool)]}
+11 -5
View File
@@ -63,7 +63,7 @@ import Simplex.Chat.Library.Subscriber
import Simplex.Chat.Badges (BadgeCredential (..), LocalBadge (..), maxXFTPFileSize, mkBadgeStatus, verifyCredential)
import Simplex.Chat.Names (SimplexDomainProof (..), SimplexDomainClaim (..), claimDomain, mkDomainClaim)
import Simplex.Chat.Names.Protocol
import Simplex.Chat.Names.Snrc (Intent (..), SignedIntent (..), SnrcDeployment (..), parseRecordKey, signSnrcIntent)
import Simplex.Chat.Names.Snrc (Intent (..), SignedIntent (..), SnrcDeployment (..), devChainId, parseRecordKey, signSnrcIntent)
import Simplex.Messaging.Eth.Address (Address, mkAddress)
import Simplex.Chat.Store.Wallets (bindSeedAccount, createSeed, currentSeed, getNameKeys, getOrCreateAccountRef, listSeeds, markBackedUp, nameKeyPathTaken, raiseNextAccountIndex, raiseNextNameIndex, recordNameKey, seedOfName, setCurrentSeed, setNextNameIndex, takeNameIndex)
import Simplex.Chat.Wallet (AccountIndex, AccountRef (..), NameIndex, SeedId, WalletAccount, WalletSeed (..), accountAddress, deriveAtPath, deriveNameKey, ethSignatureBytes, importRecoveryKey, newSeed, parseNameKeyPath, recoveryKeyPhrase, renderNameKeyPath)
@@ -1511,10 +1511,14 @@ processChatCommand cxt nm = \case
pure $ CRNames user rows
APINameInfo sendTarget nm' -> withUser $ \user -> do
cReq <- resolveServiceTarget nm user sendTarget
(_, path, _) <- nameKeyOf nm'
(_, path, acc) <- nameKeyOf nm'
namesRPC user cReq (NRResolve nm') >>= \case
NRPRecord {nrName, nrOwner, nrContact, nrChannel, nrExpiry, nrEditsLeft} ->
pure $ CRNameInfo user nrName (tshow nrOwner) path nrContact nrChannel nrExpiry nrEditsLeft
NRPRecord {nrName, nrOwner, nrContact, nrChannel, nrExpiry, nrEditsLeft} -> do
-- The service's word against our own key. A registrar that misreports
-- the owner cannot be caught anywhere else, and we are holding the
-- address it should have named.
let ours = accountAddress acc
pure $ CRNameInfo user nrName (tshow nrOwner) (nrOwner == ours) path nrContact nrChannel nrExpiry nrEditsLeft
_ -> throwCmdError "unexpected resolve response"
APINameSetLink sendTarget nm' record lnk -> withUser $ \user -> do
cReq <- resolveServiceTarget nm user sendTarget
@@ -5208,7 +5212,9 @@ clientDeployment :: SnrcDeployment
clientDeployment =
SnrcDeployment
{ sdTld = "simplex",
sdChainId = 1,
-- Not 1: these are placeholder contracts, and a domain separator that
-- says "mainnet" is one that a real deployment could be made to accept.
sdChainId = devChainId,
sdRegistrar = mockClientAddr 1,
sdResolver = mockClientAddr 2
}
+3
View File
@@ -239,6 +239,7 @@ data NamesErrorCode
| NECInternal
| NECNameReserved
| NECNameTooShort
| NECNameInvalid
| NECPaymentRejected
| NECCodeSpent
| NECCodeExpired
@@ -259,6 +260,7 @@ instance TextEncoding NamesErrorCode where
NECInternal -> "internal"
NECNameReserved -> "name_reserved"
NECNameTooShort -> "name_too_short"
NECNameInvalid -> "name_invalid"
NECPaymentRejected -> "payment_rejected"
NECCodeSpent -> "code_spent"
NECCodeExpired -> "code_expired"
@@ -276,6 +278,7 @@ instance TextEncoding NamesErrorCode where
"internal" -> NECInternal
"name_reserved" -> NECNameReserved
"name_too_short" -> NECNameTooShort
"name_invalid" -> NECNameInvalid
"payment_rejected" -> NECPaymentRejected
"code_spent" -> NECCodeSpent
"code_expired" -> NECCodeExpired
+7
View File
@@ -20,6 +20,7 @@ module Simplex.Chat.Names.Snrc
intent712,
intentDigest,
signSnrcIntent,
devChainId,
)
where
@@ -76,6 +77,12 @@ data SignedIntent = SignedIntent
setTextTypeString :: ByteString
setTextTypeString = "SetText(bytes32 node,string key,string value,uint256 nonce,uint256 deadline)"
-- | The chain the placeholder deployment claims. Deliberately not 1: signatures
-- carry their chain id, and one that reads as mainnet is one that a contract
-- deployed at the placeholder address could later be made to honour.
devChainId :: Integer
devChainId = 31337
labelHash :: ByteString -> ByteString
labelHash = keccak256
+2 -2
View File
@@ -211,10 +211,10 @@ chatResponseToView hu cfg@ChatConfig {logLevel, showReactions, showFullLinks, te
ttyUser u $ case rows of
[] -> ["no names yet - buy one with /name buy <label> <code>"]
_ -> map (\(n, points, expiry, edits) -> plain $ " " <> n <> " -> " <> points <> " expires " <> tshow expiry <> ", " <> tshow edits <> " edits left") rows
CRNameInfo u n owner path contact channel expiry edits ->
CRNameInfo u n owner ourKey path contact channel expiry edits ->
ttyUser u $
[ plain $ n,
plain $ " owner " <> owner,
plain $ " owner " <> owner <> (if ourKey then " (matches your key)" else " (NOT your key)"),
plain $ " path " <> path
]
<> map (\c -> plain $ " contact " <> c) contact
+11 -1
View File
@@ -218,10 +218,20 @@ signIntent a Eip712Intent {eiDomain, eiTypeString, eiValues} = do
}
-- | Parse @r || s || v@ as it arrives from a client.
-- | Half the secp256k1 group order. EIP-2 accepts only the lower half: for
-- every signature there is a second one at @n - s@ that recovers the same
-- signer, and accepting both means one authorisation has two identities.
secp256k1HalfN :: Integer
secp256k1HalfN = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0
parseEthSignature :: ByteString -> Either String EthSignature
parseEthSignature bs
| B.length bs /= 65 = Left "signature: expected 65 bytes"
| otherwise = Right EthSignature {esR = B.take 32 bs, esS = B.take 32 (B.drop 32 bs), esV = B.last bs}
| beInteger s > secp256k1HalfN = Left "signature: s is not canonical (EIP-2)"
| otherwise = Right EthSignature {esR = B.take 32 bs, esS = s, esV = B.last bs}
where
s = B.take 32 (B.drop 32 bs)
beInteger = B.foldl' (\acc w -> acc * 256 + fromIntegral w) 0
-- | Recover the address that produced a signature over a digest — what the
-- relayer and the contracts do.