Skip to content

Commit

Permalink
Rollback SEP23 (Muxed Account strkeys) support. (#349)
Browse files Browse the repository at this point in the history
* Don't accept muxed accounts as a destination.

* Always encode xdr.MuxedAccount to G addresses.

* Rename helper function.

* Always show ed25219 address in transaction source and fee bump fee source.

* Remove SEP23 support.

* Update changelog.
  • Loading branch information
abuiles authored May 22, 2020
1 parent 783f1ad commit 50f8050
Show file tree
Hide file tree
Showing 15 changed files with 118 additions and 275 deletions.
28 changes: 6 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Remove

- Rollback support for SEP23 (Muxed Account StrKey) ([#349](https://github.com/stellar/js-stellar-base/pull/349)).

## [v3.0.2](https://github.com/stellar/js-stellar-base/compare/v3.0.1..v3.0.2)

### Fix
Expand All @@ -20,35 +24,15 @@ This version brings protocol 13 support with backwards compatibility support for
- Add `TransactionBuilder.buildFeeBumpTransaction` which makes it easy to create `FeeBumpTransaction` ([#321](https://github.com/stellar/js-stellar-base/pull/321)).
- Adds a feature flag which allow consumers of this library to create V1 (protocol 13) transactions using the `TransactionBuilder` ([#321](https://github.com/stellar/js-stellar-base/pull/321)).
- Add support for [CAP0027](https://github.com/stellar/stellar-protocol/blob/master/core/cap-0027.md): First-class multiplexed accounts ([#325](https://github.com/stellar/js-stellar-base/pull/325)).
- Add `Keypair.xdrMuxedAccount` which creates a new `xdr.MuxedAccount`([#325](https://github.com/stellar/js-stellar-base/pull/325)).
- ~Add `Keypair.xdrMuxedAccount` which creates a new `xdr.MuxedAccount`([#325](https://github.com/stellar/js-stellar-base/pull/325)).~
- Add `FeeBumpTransaction` which makes it easy to work with fee bump transactions ([#328](https://github.com/stellar/js-stellar-base/pull/328)).
- Add `TransactionBuilder.fromXDR` which receives an xdr envelope and return a `Transaction` or `FeeBumpTransaction` ([#328](https://github.com/stellar/js-stellar-base/pull/328)).

### Update
- Update XDR definitions with protocol 13 ([#317](https://github.com/stellar/js-stellar-base/pull/317)).
- Extend `Transaction` to work with `TransactionV1Envelope` and `TransactionV0Envelope` ([#317](https://github.com/stellar/js-stellar-base/pull/317)).
- Add backward compatibility support for [CAP0018](https://github.com/stellar/stellar-protocol/blob/f01c9354aaab1e8ca97a25cf888829749cadf36a/core/cap-0018.md) ([#317](https://github.com/stellar/js-stellar-base/pull/317)).
- Update operations builder to support multiplexed accounts ([#337](https://github.com/stellar/js-stellar-base/pull/337)).

This allows you to specify an `M` account as the destination or source:
```
var destination = 'MAAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITLVL6';
var amount = '1000.0000000';
var asset = new StellarBase.Asset(
'USDUSD',
'GDGU5OAPHNPU5UCLE5RDJHG7PXZFQYWKCFOEXSXNMR6KRQRI5T6XXCD7'
);
var source =
'MAAAAAAAAAAAAAB7BQ2L7E5NBWMXDUCMZSIPOBKRDSBYVLMXGSSKF6YNPIB7Y77ITLVL6';
StellarBase.Operation.payment({
destination,
asset,
amount,
source
});
```

**To use multiplexed accounts you need a Stellar network instance running Protocol 13 or higher**
- ~Update operations builder to support multiplexed accounts ([#337](https://github.com/stellar/js-stellar-base/pull/337)).~

### Breaking changes

Expand Down
4 changes: 2 additions & 2 deletions src/fee_bump_transaction.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import xdr from './generated/stellar-xdr_generated';
import { hash } from './hashing';

import { StrKey } from './strkey';
import { Transaction } from './transaction';
import { TransactionBase } from './transaction_base';
import { encodeMuxedAccountToAddress } from './util/decode_encode_muxed_account';

/**
* Use {@link TransactionBuilder.buildFeeBumpTransaction} to build a
Expand Down Expand Up @@ -42,7 +42,7 @@ export class FeeBumpTransaction extends TransactionBase {
const innerTxEnvelope = xdr.TransactionEnvelope.envelopeTypeTx(
tx.innerTx().v1()
);
this._feeSource = StrKey.encodeMuxedAccount(this.tx.feeSource().toXDR());
this._feeSource = encodeMuxedAccountToAddress(this.tx.feeSource());
this._innerTransaction = new Transaction(
innerTxEnvelope,
networkPassphrase
Expand Down
21 changes: 10 additions & 11 deletions src/operation.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { Asset } from './asset';
import { StrKey } from './strkey';
import xdr from './generated/stellar-xdr_generated';
import * as ops from './operations/index';
import {
decodeAddressToMuxedAccount,
encodeMuxedAccountToAddress
} from './util/decode_encode_muxed_account';

const ONE = 10000000;
const MAX_INT64 = '9223372036854775807';
Expand Down Expand Up @@ -62,9 +66,7 @@ export class Operation {
static setSourceAccount(opAttributes, opts) {
if (opts.source) {
try {
opAttributes.sourceAccount = xdr.MuxedAccount.fromXDR(
StrKey.decodeMuxedAccount(opts.source)
);
opAttributes.sourceAccount = decodeAddressToMuxedAccount(opts.source);
} catch (e) {
throw new Error('Source address is invalid');
}
Expand All @@ -81,13 +83,10 @@ export class Operation {
function accountIdtoAddress(accountId) {
return StrKey.encodeEd25519PublicKey(accountId.ed25519());
}
function muxedAccounttoAddress(accountId) {
return StrKey.encodeMuxedAccount(accountId.toXDR());
}

const result = {};
if (operation.sourceAccount()) {
result.source = muxedAccounttoAddress(operation.sourceAccount());
result.source = encodeMuxedAccountToAddress(operation.sourceAccount());
}

const attrs = operation.body().value();
Expand All @@ -102,7 +101,7 @@ export class Operation {
}
case 'payment': {
result.type = 'payment';
result.destination = muxedAccounttoAddress(attrs.destination());
result.destination = encodeMuxedAccountToAddress(attrs.destination());
result.asset = Asset.fromOperation(attrs.asset());
result.amount = this._fromXDRAmount(attrs.amount());
break;
Expand All @@ -111,7 +110,7 @@ export class Operation {
result.type = 'pathPaymentStrictReceive';
result.sendAsset = Asset.fromOperation(attrs.sendAsset());
result.sendMax = this._fromXDRAmount(attrs.sendMax());
result.destination = muxedAccounttoAddress(attrs.destination());
result.destination = encodeMuxedAccountToAddress(attrs.destination());
result.destAsset = Asset.fromOperation(attrs.destAsset());
result.destAmount = this._fromXDRAmount(attrs.destAmount());
result.path = [];
Expand All @@ -128,7 +127,7 @@ export class Operation {
result.type = 'pathPaymentStrictSend';
result.sendAsset = Asset.fromOperation(attrs.sendAsset());
result.sendAmount = this._fromXDRAmount(attrs.sendAmount());
result.destination = muxedAccounttoAddress(attrs.destination());
result.destination = encodeMuxedAccountToAddress(attrs.destination());
result.destAsset = Asset.fromOperation(attrs.destAsset());
result.destMin = this._fromXDRAmount(attrs.destMin());
result.path = [];
Expand Down Expand Up @@ -233,7 +232,7 @@ export class Operation {
}
case 'accountMerge': {
result.type = 'accountMerge';
result.destination = muxedAccounttoAddress(attrs);
result.destination = encodeMuxedAccountToAddress(attrs);
break;
}
case 'manageDatum': {
Expand Down
4 changes: 2 additions & 2 deletions src/operations/account_merge.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import xdr from '../generated/stellar-xdr_generated';
import { StrKey } from '../strkey';
import { decodeAddressToMuxedAccount } from '../util/decode_encode_muxed_account';

/**
* Transfers native balance to destination account.
Expand All @@ -14,7 +14,7 @@ export function accountMerge(opts) {
const opAttributes = {};
try {
opAttributes.body = xdr.OperationBody.accountMerge(
xdr.MuxedAccount.fromXDR(StrKey.decodeMuxedAccount(opts.destination))
decodeAddressToMuxedAccount(opts.destination)
);
} catch (e) {
throw new Error('destination is invalid');
Expand Down
6 changes: 2 additions & 4 deletions src/operations/path_payment_strict_receive.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import xdr from '../generated/stellar-xdr_generated';
import { StrKey } from '../strkey';
import { decodeAddressToMuxedAccount } from '../util/decode_encode_muxed_account';

/**
* Returns a XDR PathPaymentStrictReceiveOp. A `PathPaymentStrictReceive` operation send the specified amount to the
Expand Down Expand Up @@ -36,9 +36,7 @@ export function pathPaymentStrictReceive(opts) {
attributes.sendMax = this._toXDRAmount(opts.sendMax);

try {
attributes.destination = xdr.MuxedAccount.fromXDR(
StrKey.decodeMuxedAccount(opts.destination)
);
attributes.destination = decodeAddressToMuxedAccount(opts.destination);
} catch (e) {
throw new Error('destination is invalid');
}
Expand Down
6 changes: 2 additions & 4 deletions src/operations/path_payment_strict_send.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import xdr from '../generated/stellar-xdr_generated';
import { StrKey } from '../strkey';
import { decodeAddressToMuxedAccount } from '../util/decode_encode_muxed_account';

/**
* Returns a XDR PathPaymentStrictSendOp. A `PathPaymentStrictSend` operation send the specified amount to the
Expand Down Expand Up @@ -35,9 +35,7 @@ export function pathPaymentStrictSend(opts) {
attributes.sendAsset = opts.sendAsset.toXDRObject();
attributes.sendAmount = this._toXDRAmount(opts.sendAmount);
try {
attributes.destination = xdr.MuxedAccount.fromXDR(
StrKey.decodeMuxedAccount(opts.destination)
);
attributes.destination = decodeAddressToMuxedAccount(opts.destination);
} catch (e) {
throw new Error('destination is invalid');
}
Expand Down
6 changes: 2 additions & 4 deletions src/operations/payment.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import xdr from '../generated/stellar-xdr_generated';
import { StrKey } from '../strkey';
import { decodeAddressToMuxedAccount } from '../util/decode_encode_muxed_account';

/**
* Create a payment operation.
Expand All @@ -22,9 +22,7 @@ export function payment(opts) {

const attributes = {};
try {
attributes.destination = xdr.MuxedAccount.fromXDR(
StrKey.decodeMuxedAccount(opts.destination)
);
attributes.destination = decodeAddressToMuxedAccount(opts.destination);
} catch (e) {
throw new Error('destination is invalid');
}
Expand Down
44 changes: 1 addition & 43 deletions src/strkey.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import isUndefined from 'lodash/isUndefined';
import isNull from 'lodash/isNull';
import isString from 'lodash/isString';
import { verifyChecksum } from './util/checksum';
import xdr from './generated/stellar-xdr_generated';

const versionBytes = {
ed25519PublicKey: 6 << 3, // G
ed25519SecretSeed: 18 << 3, // S
preAuthTx: 19 << 3, // T
sha256Hash: 23 << 3, // X
muxedAccount: 12 << 3 // M
sha256Hash: 23 << 3 // X
};

/**
Expand Down Expand Up @@ -109,46 +107,6 @@ export class StrKey {
static decodeSha256Hash(data) {
return decodeCheck('sha256Hash', data);
}

/**
* Encodes data to strkey.
* @param {Buffer} data data to encode. It must represent a valid xdr.MuxedAccount
* @returns {string}
*/
static encodeMuxedAccount(data) {
const muxed = xdr.MuxedAccount.fromXDR(data);

if (muxed.switch() === xdr.CryptoKeyType.keyTypeEd25519()) {
return encodeCheck('ed25519PublicKey', muxed.ed25519());
}

return encodeCheck('muxedAccount', muxed.med25519().toXDR());
}

/**
* Decodes strkey muxed account to raw data. The raw data can be used to create a valid xdr.MuxedAccount
* @param {string} data data to decode
* @returns {Buffer}
*/
static decodeMuxedAccount(data) {
let muxed;
switch (data.length) {
case 56:
muxed = xdr.MuxedAccount.keyTypeEd25519(
decodeCheck('ed25519PublicKey', data)
);
break;
case 69:
muxed = xdr.MuxedAccount.keyTypeMuxedEd25519(
xdr.MuxedAccountMed25519.fromXDR(decodeCheck('muxedAccount', data))
);
break;
default:
throw new Error('invalid encoded string');
}

return muxed.toXDR();
}
}

function isValid(versionByteName, encoded) {
Expand Down
5 changes: 2 additions & 3 deletions src/transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { StrKey } from './strkey';
import { Operation } from './operation';
import { Memo } from './memo';
import { TransactionBase } from './transaction_base';
import { encodeMuxedAccountToAddress } from './util/decode_encode_muxed_account';

/**
* Use {@link TransactionBuilder} to build a transaction object. If you have
Expand Down Expand Up @@ -56,9 +57,7 @@ export class Transaction extends TransactionBase {
);
break;
default:
this._source = StrKey.encodeMuxedAccount(
this.tx.sourceAccount().toXDR()
);
this._source = encodeMuxedAccountToAddress(this.tx.sourceAccount());
break;
}

Expand Down
31 changes: 31 additions & 0 deletions src/util/decode_encode_muxed_account.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import xdr from '../generated/stellar-xdr_generated';
import { StrKey } from '../strkey';

/**
* Returns a XDR.MuxedAccount forcing the ed25519 discriminant.
* @function
* @param {string} address address to encode to XDR.
* @returns {xdr.MuxedAccount} MuxedAccount with ed25519 discriminant.
*/
export function decodeAddressToMuxedAccount(address) {
return xdr.MuxedAccount.keyTypeEd25519(
StrKey.decodeEd25519PublicKey(address)
);
}

/**
* Converts an xdr.MuxedAccount to its string representation, forcing the ed25519 representation.
* @function
* @param {xdr.MuxedAccount} muxedAccount .
* @returns {string} address
*/
export function encodeMuxedAccountToAddress(muxedAccount) {
let ed25519;
if (muxedAccount.switch() === xdr.CryptoKeyType.keyTypeEd25519()) {
ed25519 = muxedAccount.ed25519();
} else {
ed25519 = muxedAccount.med25519().ed25519();
}

return StrKey.encodeEd25519PublicKey(ed25519);
}
4 changes: 1 addition & 3 deletions test/unit/fee_bump_transation_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,7 @@ describe('FeeBumpTransaction', function() {
envelope,
this.networkPassphrase
);
expect(txWithMuxedAccount.feeSource).to.equal(
StellarBase.StrKey.encodeMuxedAccount(muxedAccount.toXDR())
);
expect(txWithMuxedAccount.feeSource).to.equal(this.feeSource.publicKey());
});
});

Expand Down
Loading

0 comments on commit 50f8050

Please sign in to comment.