Skip to content

Commit

Permalink
Merge pull request #134 from Juneo-io/signers-update
Browse files Browse the repository at this point in the history
Signers update
  • Loading branch information
alekswaslet authored Jun 14, 2024
2 parents df37f5e + 08feb5a commit 40cec1c
Show file tree
Hide file tree
Showing 14 changed files with 149 additions and 139 deletions.
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

0 comments on commit 40cec1c

Please sign in to comment.