Skip to content

Commit

Permalink
Add recoverUnsignedTx to EthereumSignedTransaction
Browse files Browse the repository at this point in the history
  • Loading branch information
Florian-S-A-W committed Apr 30, 2024
1 parent 76f8bd6 commit 76bc74b
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 94 deletions.
136 changes: 70 additions & 66 deletions Sources/Core/Transaction/EthereumTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,19 +124,8 @@ public struct EthereumTransaction: Codable {
guard let nonce = nonce, let gasPrice = gasPrice, let gasLimit = gasLimit, let value = value else {
throw EthereumSignedTransaction.Error.transactionInvalid
}
let rlp = RLPItem(
nonce: nonce,
gasPrice: gasPrice,
gasLimit: gasLimit,
to: to,
value: value,
data: data,
v: chainId,
r: 0,
s: 0
)
let rawRlp = try RLPEncoder().encode(rlp)
let signature = try privateKey.sign(message: rawRlp)
let messageToSign = try self.messageToSign(chainId: chainId)
let signature = try privateKey.sign(message: messageToSign)

let v: BigUInt
if chainId.quantity == 0 {
Expand Down Expand Up @@ -190,24 +179,8 @@ public struct EthereumTransaction: Codable {
if chainId.quantity == BigUInt(0) {
throw EthereumSignedTransaction.Error.chainIdNotSet(msg: "EIP1559 transactions need a chainId")
}

let rlp = RLPItem(
nonce: nonce,
gasPrice: gasPrice ?? EthereumQuantity(integerLiteral: 0),
maxFeePerGas: maxFeePerGas,
maxPriorityFeePerGas: maxPriorityFeePerGas,
gasLimit: gasLimit,
to: to,
value: value,
data: data,
chainId: chainId,
accessList: accessList,
transactionType: transactionType
)
let rawRlp = try RLPEncoder().encode(rlp)
var messageToSign = Bytes()
messageToSign.append(0x02)
messageToSign.append(contentsOf: rawRlp)

var messageToSign = try self.messageToSign(chainId: chainId)
let signature = try privateKey.sign(message: messageToSign)

let v = BigUInt(signature.v)
Expand All @@ -233,6 +206,58 @@ public struct EthereumTransaction: Codable {
}
}

public extension EthereumTransaction {

fileprivate func messageToSign(chainId: EthereumQuantity) throws -> Bytes {
let rlpEncoder = RLPEncoder()

if self.transactionType == .legacy {
guard let nonce = nonce, let gasPrice = gasPrice, let gasLimit = gasLimit, let value = value else {
throw EthereumSignedTransaction.Error.transactionInvalid
}
let rlp = RLPItem(
nonce: nonce,
gasPrice: gasPrice,
gasLimit: gasLimit,
to: to,
value: value,
data: data,
v: chainId,
r: 0,
s: 0
)
let rawRlp = try RLPEncoder().encode(rlp)
return rawRlp
} else if self.transactionType == .eip1559 {
guard let nonce = nonce, let maxFeePerGas = maxFeePerGas, let maxPriorityFeePerGas = maxPriorityFeePerGas,
let gasLimit = gasLimit, let value = value else {
throw EthereumSignedTransaction.Error.transactionInvalid
}
let rlp = RLPItem(
nonce: nonce,
gasPrice: gasPrice ?? EthereumQuantity(integerLiteral: 0),
maxFeePerGas: maxFeePerGas,
maxPriorityFeePerGas: maxPriorityFeePerGas,
gasLimit: gasLimit,
to: to,
value: value,
data: data,
chainId: chainId,
accessList: accessList,
transactionType: transactionType
)
let rawRlp = try rlpEncoder.encode(rlp)
var messageToSign = Bytes()
messageToSign.append(0x02)
messageToSign.append(contentsOf: rawRlp)

return messageToSign
} else {
throw EthereumSignedTransaction.Error.transactionInvalid
}
}
}

public struct EthereumSignedTransaction {

// MARK: - Properties
Expand Down Expand Up @@ -720,7 +745,7 @@ extension EthereumSignedTransaction {
}

public func publicKey() throws -> EthereumPublicKey {
let messageToSign = try self.unsignedMessage()
let messageToSign = try self.unsignedTransaction().messageToSign(chainId: self.chainId)
var recId: BigUInt
if v.quantity >= BigUInt(35) + (BigUInt(2) * chainId.quantity) {
recId = v.quantity - BigUInt(35) - (BigUInt(2) * chainId.quantity)
Expand All @@ -734,40 +759,19 @@ extension EthereumSignedTransaction {
return try EthereumPublicKey(message: messageToSign, v: EthereumQuantity(quantity: recId), r: self.r, s: self.s)
}

private func unsignedMessage() throws -> Bytes {
let rlpEncoder = RLPEncoder()

if self.transactionType == .legacy {
let legacyrlp = RLPItem(
nonce: self.nonce,
gasPrice: self.gasPrice,
gasLimit: self.gasLimit,
to: self.to,
value: self.value,
data: self.data,
v: self.chainId,
r: 0,
s: 0
)
let rawRlp = try RLPEncoder().encode(legacyrlp)
return rawRlp
} else if self.transactionType == .eip1559 {
let rlp = self.rlp()

if let arr = rlp.array{
let unsignedRlp = Array(arr[0..<(arr.count - 3)])
var messageToSign = Bytes()
let unsignedRlpBytes = try rlpEncoder.encode(RLPItem.array(unsignedRlp))
messageToSign.append(0x02)
messageToSign.append(contentsOf: unsignedRlpBytes)
return messageToSign
} else {
throw Error.transactionInvalid
}

} else {
throw Error.rlpItemInvalid
}
public func unsignedTransaction() throws -> EthereumTransaction {
return EthereumTransaction(
nonce: self.nonce,
gasPrice: self.gasPrice,
maxFeePerGas: self.maxFeePerGas,
maxPriorityFeePerGas: self.maxPriorityFeePerGas,
gasLimit: self.gasLimit,
to: self.to,
value: self.value,
data: self.data,
accessList: self.accessList,
transactionType: self.transactionType
)
}

}
Loading

0 comments on commit 76bc74b

Please sign in to comment.