Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signers update #134

Merged
merged 3 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/api/platform/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export interface ValidatorData {
delegationFee: string
uptime: string
connected: boolean
signer: Signer
signer: ValidatorSigner
delegatorCount: string
delegatorWeight: string
}
Expand All @@ -58,7 +58,7 @@ export interface RewardOwner {
addresses: string[]
}

export interface Signer {
export interface ValidatorSigner {
publicKey: string
proofOfPossession: string
}
Expand Down
22 changes: 11 additions & 11 deletions src/transaction/input.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { type Blockchain } from '../chain'
import { InputError, JuneoBuffer, ParsingError, type Serializable, SignatureError } from '../utils'
import { type VMWallet } from '../wallet'
import { AssetIdSize, Secp256k1InputTypeId, TransactionIdSize } from './constants'
import { type Utxo } from './output'
import { type Signable } from './signature'
import { type Address, AssetId, Signature, TransactionId } from './types'
import { type Signable, type Signer } from './signature'
import { AssetId, Signature, TransactionId } from './types'

export class UserInput {
assetId: string
Expand Down Expand Up @@ -66,24 +65,25 @@ export class TransferableInput implements Serializable, Signable, Spendable {
return this.assetId
}

sign (bytes: JuneoBuffer, wallets: VMWallet[]): Signature[] {
async sign (bytes: JuneoBuffer, signers: Signer[]): Promise<Signature[]> {
if (this.input.utxo === undefined) {
throw new SignatureError('cannot sign read only inputs')
}
const indices: number[] = this.input.addressIndices
const indices = this.input.addressIndices
const signatures: Signature[] = []
const threshold: number = this.input.utxo.output.threshold
const threshold = this.input.utxo.output.threshold
for (let i = 0; i < threshold && i < indices.length; i++) {
const address: Address = this.input.utxo.output.addresses[indices[i]]
for (const wallet of wallets) {
if (address.matches(wallet.getJuneoAddress())) {
signatures.push(new Signature(wallet.sign(bytes)))
const address = this.input.utxo.output.addresses[indices[i]]
for (const signer of signers) {
if (signer.matches(address)) {
const signature = await signer.sign(bytes)
signatures.push(new Signature(signature))
break
}
}
}
if (signatures.length < threshold) {
throw new SignatureError('missing wallets to complete signatures')
throw new SignatureError('missing signer to complete signatures')
}
return signatures
}
Expand Down
29 changes: 15 additions & 14 deletions src/transaction/jevm/transaction.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { JuneoBuffer, type Serializable, SignatureError } from '../../utils'
import { type VMWallet } from '../../wallet'
import {
AssetIdSize,
BlockchainIdSize,
Expand All @@ -12,7 +11,7 @@ import {
} from '../constants'
import { type Spendable, TransferableInput } from '../input'
import { TransferableOutput } from '../output'
import { sign, type Signable } from '../signature'
import { type Signable, SignableTx, type Signer } from '../signature'
import { Address, AssetId, type BlockchainId, Signature } from '../types'

export class EVMOutput implements Serializable {
Expand Down Expand Up @@ -64,17 +63,17 @@ export class EVMInput implements Serializable, Signable, Spendable {
return this.assetId
}

sign (bytes: JuneoBuffer, wallets: VMWallet[]): Signature[] {
async sign (bytes: JuneoBuffer, signers: Signer[]): Promise<Signature[]> {
const signatures: Signature[] = []
const address: Address = this.address
for (const wallet of wallets) {
if (address.matches(wallet.getAddress())) {
signatures.push(new Signature(wallet.sign(bytes)))
for (const signer of signers) {
if (signer.matches(this.address)) {
const signature = await signer.sign(bytes)
signatures.push(new Signature(signature))
break
}
}
if (signatures.length < 1) {
throw new SignatureError('missing wallets to complete signatures')
throw new SignatureError('missing signer to complete signatures')
}
return signatures
}
Expand All @@ -97,7 +96,7 @@ export class EVMInput implements Serializable, Signable, Spendable {
}
}

export class JEVMExportTransaction implements Serializable {
export class JEVMExportTransaction extends SignableTx implements Serializable {
codecId: number = CodecId
typeId: number = EVMExportTransactionTypeId
networkId: number
Expand All @@ -113,6 +112,7 @@ export class JEVMExportTransaction implements Serializable {
inputs: EVMInput[],
exportedOutputs: TransferableOutput[]
) {
super()
this.networkId = networkId
this.blockchainId = blockchainId
this.destinationChain = destinationChain
Expand All @@ -122,8 +122,8 @@ export class JEVMExportTransaction implements Serializable {
this.exportedOutputs.sort(TransferableOutput.comparator)
}

signTransaction (wallets: VMWallet[]): JuneoBuffer {
return sign(this.serialize(), this.inputs, wallets)
async signTransaction (signers: Signer[]): Promise<JuneoBuffer> {
return await super.sign(this.serialize(), this.inputs, signers)
}

serialize (): JuneoBuffer {
Expand Down Expand Up @@ -188,7 +188,7 @@ export class JEVMExportTransaction implements Serializable {
}
}

export class JEVMImportTransaction implements Serializable {
export class JEVMImportTransaction extends SignableTx implements Serializable {
codecId: number = CodecId
typeId: number = EVMImportTransactionTypeId
networkId: number
Expand All @@ -204,6 +204,7 @@ export class JEVMImportTransaction implements Serializable {
importedInputs: TransferableInput[],
outputs: EVMOutput[]
) {
super()
this.networkId = networkId
this.blockchainId = blockchainId
this.sourceChain = sourceChain
Expand All @@ -213,8 +214,8 @@ export class JEVMImportTransaction implements Serializable {
this.outputs.sort(EVMOutput.comparator)
}

signTransaction (wallets: VMWallet[]): JuneoBuffer {
return sign(this.serialize(), this.importedInputs, wallets)
async signTransaction (signers: Signer[]): Promise<JuneoBuffer> {
return await super.sign(this.serialize(), this.importedInputs, signers)
}

serialize (): JuneoBuffer {
Expand Down
18 changes: 9 additions & 9 deletions src/transaction/platform/supernet.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { type Serializable, JuneoBuffer, SignatureError } from '../../utils'
import { type VMWallet } from '../../wallet'
import { getSignersIndices } from '../builder'
import { EmptySignerTypeId, PrimarySignerTypeId, SupernetAuthTypeId } from '../constants'
import { type Signable } from '../signature'
import { type Signable, type Signer } from '../signature'
import { type Address, type BLSPublicKey, type BLSSignature, Signature } from '../types'
import { type Secp256k1OutputOwners } from './validation'

Expand All @@ -19,20 +18,21 @@ export class SupernetAuth implements Serializable, Signable {
this.rewardsOwner = rewardsOwner
}

sign (bytes: JuneoBuffer, wallets: VMWallet[]): Signature[] {
async sign (bytes: JuneoBuffer, signers: Signer[]): Promise<Signature[]> {
const signatures: Signature[] = []
const threshold: number = this.rewardsOwner.threshold
const threshold = this.rewardsOwner.threshold
for (let i = 0; i < threshold && i < this.addressIndices.length; i++) {
const address: Address = this.rewardsOwner.addresses[i]
for (const wallet of wallets) {
if (address.matches(wallet.getJuneoAddress())) {
signatures.push(new Signature(wallet.sign(bytes)))
const address = this.rewardsOwner.addresses[i]
for (const signer of signers) {
if (signer.matches(address)) {
const signature = await signer.sign(bytes)
signatures.push(new Signature(signature))
break
}
}
}
if (signatures.length < threshold) {
throw new SignatureError('missing wallets to complete supernet signatures')
throw new SignatureError('missing signer to complete supernet signatures')
}
return signatures
}
Expand Down
46 changes: 26 additions & 20 deletions src/transaction/signature.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { JuneoBuffer, type Serializable } from '../utils'
import { type VMWallet } from '../wallet'
import { Secp256k1CredentialsTypeId, SignatureSize } from './constants'
import { type Signature } from './types'
import { type Address, type Signature } from './types'

export interface Signer {
sign: (bytes: JuneoBuffer) => Promise<JuneoBuffer>
matches: (address: Address) => boolean
}

export interface Signable {
sign: (bytes: JuneoBuffer, wallets: VMWallet[]) => Signature[]
sign: (bytes: JuneoBuffer, signers: Signer[]) => Promise<Signature[]>
}

export abstract class TransactionCredentials implements Serializable {
Expand Down Expand Up @@ -40,22 +44,24 @@ export class Secp256k1Credentials extends TransactionCredentials {
}
}

export function sign (bytes: JuneoBuffer, unsignedInputs: Signable[], wallets: VMWallet[]): JuneoBuffer {
const credentials: JuneoBuffer[] = []
let credentialsSize: number = 0
for (const input of unsignedInputs) {
const signatures: Signature[] = input.sign(bytes, wallets)
const credential: TransactionCredentials = new Secp256k1Credentials(signatures)
const credentialBytes: JuneoBuffer = credential.serialize()
credentialsSize += credentialBytes.length
credentials.push(credentialBytes)
}
const buffer: JuneoBuffer = JuneoBuffer.alloc(bytes.length + 4 + credentialsSize)
buffer.write(bytes)
buffer.writeUInt32(credentials.length)
credentials.sort(JuneoBuffer.comparator)
for (const credential of credentials) {
buffer.write(credential)
export abstract class SignableTx {
async sign (bytes: JuneoBuffer, unsignedInputs: Signable[], signers: Signer[]): Promise<JuneoBuffer> {
const credentials: JuneoBuffer[] = []
let credentialsSize: number = 0
for (const input of unsignedInputs) {
const signatures = await input.sign(bytes, signers)
const credential = new Secp256k1Credentials(signatures)
const credentialBytes = credential.serialize()
credentialsSize += credentialBytes.length
credentials.push(credentialBytes)
}
const buffer: JuneoBuffer = JuneoBuffer.alloc(bytes.length + 4 + credentialsSize)
buffer.write(bytes)
buffer.writeUInt32(credentials.length)
credentials.sort(JuneoBuffer.comparator)
for (const credential of credentials) {
buffer.write(credential)
}
return buffer
}
return buffer
}
12 changes: 6 additions & 6 deletions src/transaction/transaction.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { type Blockchain } from '../chain'
import { JuneoBuffer, type Serializable } from '../utils'
import { type VMWallet } from '../wallet'
import { BlockchainIdSize, CodecId } from './constants'
import { TransferableInput } from './input'
import { TransferableOutput, type Utxo } from './output'
import { type Signable, sign } from './signature'
import { SignableTx, type Signable, type Signer } from './signature'
import { type BlockchainId } from './types'

export class TransactionFee {
Expand Down Expand Up @@ -33,10 +32,10 @@ export interface UnsignedTransaction extends Serializable {
memo: string
getSignables: () => Signable[]
getUtxos: () => Utxo[]
signTransaction: (wallets: VMWallet[]) => JuneoBuffer
signTransaction: (signers: Signer[]) => Promise<JuneoBuffer>
}

export abstract class AbstractBaseTransaction implements UnsignedTransaction {
export abstract class AbstractBaseTransaction extends SignableTx implements UnsignedTransaction {
codecId: number
typeId: number
networkId: number
Expand All @@ -53,6 +52,7 @@ export abstract class AbstractBaseTransaction implements UnsignedTransaction {
inputs: TransferableInput[],
memo: string
) {
super()
this.codecId = CodecId
this.typeId = typeId
this.networkId = networkId
Expand All @@ -76,8 +76,8 @@ export abstract class AbstractBaseTransaction implements UnsignedTransaction {
return utxos
}

signTransaction (wallets: VMWallet[]): JuneoBuffer {
return sign(this.serialize(), this.getSignables(), wallets)
async signTransaction (signers: Signer[]): Promise<JuneoBuffer> {
return await super.sign(this.serialize(), this.getSignables(), signers)
}

serialize (): JuneoBuffer {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/wallet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type Blockchain, JEVM_ID, JVM_ID, PLATFORMVM_ID } from '../chain'
import { JEVM_ID, JVM_ID, PLATFORMVM_ID, type Blockchain } from '../chain'
import { UserInput } from '../transaction'
import { BaseSpending, type ExecutableOperation, type MCNAccount, type Spending, type TransactionType } from '../wallet'
import { rmd160, sha256 } from './crypto'
Expand Down
22 changes: 11 additions & 11 deletions src/wallet/account/jvm.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { type MCNProvider } from '../../juneo'
import {
TransactionType,
type UtxoFeeData,
type UtxoSpending,
estimateSendOperation,
estimateSendUtxoOperation
} from '../transaction'
import { AccountError } from '../../utils'
import {
type ChainNetworkOperation,
type ChainOperationSummary,
type ExecutableOperation,
NetworkOperationType,
type ChainOperationSummary,
type SendOperation,
type ChainNetworkOperation,
type SendUtxoOperation
} from '../operation'
import {
TransactionType,
type UtxoFeeData,
type UtxoSpending,
estimateSendOperation,
estimateSendUtxoOperation
} from '../transaction'
import { type MCNWallet } from '../wallet'
import { UtxoAccount } from './account'

Expand Down Expand Up @@ -50,8 +50,8 @@ export class JVMAccount extends UtxoAccount {

private async executeAndTrackTransaction (summary: ChainOperationSummary, type: TransactionType): Promise<void> {
const executable: ExecutableOperation = summary.getExecutable()
const transaction: string = (summary.fee as UtxoFeeData).transaction.signTransaction(this.signers).toCHex()
const transactionHash: string = (await executable.provider.jvmApi.issueTx(transaction)).txID
const signedTx = await (summary.fee as UtxoFeeData).transaction.signTransaction(this.signers)
const transactionHash: string = (await executable.provider.jvmApi.issueTx(signedTx.toCHex())).txID
await executable.trackJVMTransaction(transactionHash, type)
}
}
Loading
Loading