Skip to content

Commit

Permalink
Merge branch 'bumpSequenceOp'
Browse files Browse the repository at this point in the history
  • Loading branch information
zulucrypto committed Apr 4, 2018
2 parents e1c23cf + 663a282 commit 1568ea3
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 3 deletions.
6 changes: 4 additions & 2 deletions src/Signing/TrezorSigner.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ public function signTransaction(TransactionBuilder $builder)

$networkPassphrase = $builder->getApiClient()->getNetworkPassphrase();

$cmd = sprintf('%s stellar_sign_transaction -a %s -n %s %s',
$bip32Path = sprintf("m/44'/148'/%s'", $this->accountIndex);

$cmd = sprintf('%s stellar_sign_transaction --address %s -n %s %s',
$this->trezorBinPath,
escapeshellarg(($this->accountIndex + 1)),
escapeshellarg($bip32Path),
escapeshellarg($networkPassphrase),
escapeshellarg(base64_encode($xdr))
);
Expand Down
11 changes: 11 additions & 0 deletions src/Transaction/TransactionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use ZuluCrypto\StellarSdk\XdrModel\Memo;
use ZuluCrypto\StellarSdk\XdrModel\Operation\AccountMergeOp;
use ZuluCrypto\StellarSdk\XdrModel\Operation\AllowTrustOp;
use ZuluCrypto\StellarSdk\XdrModel\Operation\BumpSequenceOp;
use ZuluCrypto\StellarSdk\XdrModel\Operation\ChangeTrustOp;
use ZuluCrypto\StellarSdk\XdrModel\Operation\CreateAccountOp;
use ZuluCrypto\StellarSdk\XdrModel\Operation\ManageDataOp;
Expand Down Expand Up @@ -362,6 +363,16 @@ public function clearAccountData($key, $sourceAccountId = null)
return $this->addOperation(new ManageDataOp($key, null, $sourceAccountId));
}

/**
* @param BigInteger $bumpTo
* @param null $sourceAccountId
* @return TransactionBuilder
*/
public function bumpSequenceTo(BigInteger $bumpTo, $sourceAccountId = null)
{
return $this->addOperation(new BumpSequenceOp($bumpTo, $sourceAccountId));
}

/**
* @return string
*/
Expand Down
30 changes: 30 additions & 0 deletions src/Xdr/XdrEncoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,36 @@ public static function signedBigInteger64(BigInteger $value)
return XdrEncoder::opaqueFixed($xdrBytes, 8);
}

/**
* Converts $value to an unsigned 8-byte big endian uint64
*
* @param BigInteger $value
* @return string
*/
public static function unsignedBigInteger64(BigInteger $value)
{
$xdrBytes = '';
$bigIntBytes = $value->toBytes(true);

// Special case: MAX_UINT_64 will look like 00ffffffffffffffff and have an
// extra preceeding byte we need to get rid of
if (strlen($bigIntBytes) === 9 && substr($value->toHex(true), 0, 2) === '00') {
$bigIntBytes = substr($bigIntBytes, 1);
}

$paddingChar = chr(0);

$paddingBytes = 8 - strlen($bigIntBytes);
while ($paddingBytes > 0) {
$xdrBytes .= $paddingChar;
$paddingBytes--;
}

$xdrBytes .= $bigIntBytes;

return XdrEncoder::opaqueFixed($xdrBytes, 8);
}

/**
* Use this to write raw bytes representing a 64-bit integer
*
Expand Down
67 changes: 67 additions & 0 deletions src/XdrModel/Operation/BumpSequenceOp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php


namespace ZuluCrypto\StellarSdk\XdrModel\Operation;


use phpseclib\Math\BigInteger;
use ZuluCrypto\StellarSdk\Keypair;
use ZuluCrypto\StellarSdk\Xdr\XdrBuffer;
use ZuluCrypto\StellarSdk\Xdr\XdrEncoder;
use ZuluCrypto\StellarSdk\XdrModel\AccountId;

class BumpSequenceOp extends Operation
{

/** @var BigInteger */
protected $bumpTo;

public function __construct(BigInteger $bumpTo, $sourceAccountId = null)
{
parent::__construct(Operation::TYPE_BUMP_SEQUENCE, $sourceAccountId);

$this->bumpTo = $bumpTo;
}

/**
* @return string
*/
public function toXdr()
{
$bytes = parent::toXdr();

$bytes .= XdrEncoder::unsignedBigInteger64($this->bumpTo);

return $bytes;
}

/**
* NOTE: This only parses the XDR that's specific to this operation and cannot
* load a full Operation
*
* @deprecated Do not call this directly, instead call Operation::fromXdr()
* @param XdrBuffer $xdr
* @return BumpSequenceOp
* @throws \ErrorException
*/
public static function fromXdr(XdrBuffer $xdr)
{
return new BumpSequenceOp($xdr->readBigInteger());
}

/**
* @return BigInteger
*/
public function getBumpTo()
{
return $this->bumpTo;
}

/**
* @param BigInteger $bumpTo
*/
public function setBumpTo($bumpTo)
{
$this->bumpTo = $bumpTo;
}
}
4 changes: 4 additions & 0 deletions src/XdrModel/Operation/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ abstract class Operation implements XdrEncodableInterface
const TYPE_ACCOUNT_MERGE = 8;
const TYPE_INFLATION = 9;
const TYPE_MANAGE_DATA = 10;
const TYPE_BUMP_SEQUENCE = 11;

/**
* @var AccountId
Expand Down Expand Up @@ -151,6 +152,9 @@ public static function fromXdr(XdrBuffer $xdr)
case Operation::TYPE_MANAGE_DATA:
$model = ManageDataOp::fromXdr($xdr);
break;
case Operation::TYPE_BUMP_SEQUENCE:
$model = BumpSequenceOp::fromXdr($xdr);
break;
default:
throw new \InvalidArgumentException(sprintf('unrecognized operation type %s', $type));
}
Expand Down
64 changes: 64 additions & 0 deletions tests/HardwareWallet/BumpSequenceOpTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php


namespace ZuluCrypto\StellarSdk\Test\HardwareWallet;


use phpseclib\Math\BigInteger;
use ZuluCrypto\StellarSdk\Keypair;
use ZuluCrypto\StellarSdk\Test\Util\HardwareWalletIntegrationTest;

class BumpSequenceOpTest extends HardwareWalletIntegrationTest
{
/**
* @group requires-hardwarewallet
*/
public function testSimpleBumpSequence()
{
$sourceKeypair = Keypair::newFromMnemonic($this->mnemonic);

$bumpTo = new BigInteger(1234567890);

$transaction = $this->horizonServer
->buildTransaction($sourceKeypair)
->setSequenceNumber(new BigInteger(4294967296))
->bumpSequenceTo($bumpTo);

$knownSignature = $transaction->signWith($this->privateKeySigner);

$this->manualVerificationOutput(join(PHP_EOL, [
' Bump Sequence: basic',
' Source: ' . $sourceKeypair->getPublicKey(),
' Bump To: ' . $bumpTo->toString(),
]));
$hardwareSignature = $transaction->signWith($this->horizonServer->getSigningProvider());

$this->assertEquals($knownSignature->toBase64(), $hardwareSignature->toBase64());
}

/**
* @group requires-hardwarewallet
*/
public function testMaxBumpSequence()
{
$sourceKeypair = Keypair::newFromMnemonic($this->mnemonic);

$bumpTo = new BigInteger('9223372036854775807');

$transaction = $this->horizonServer
->buildTransaction($sourceKeypair)
->setSequenceNumber(new BigInteger(4294967296))
->bumpSequenceTo($bumpTo);

$knownSignature = $transaction->signWith($this->privateKeySigner);

$this->manualVerificationOutput(join(PHP_EOL, [
' Bump Sequence: max',
' Source: ' . $sourceKeypair->getPublicKey(),
' Bump To: ' . $bumpTo->toString(),
]));
$hardwareSignature = $transaction->signWith($this->horizonServer->getSigningProvider());

$this->assertEquals($knownSignature->toBase64(), $hardwareSignature->toBase64());
}
}
18 changes: 18 additions & 0 deletions tests/Unit/Xdr/XdrEncoderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ public function testSignedBigInteger64()
$this->assertBytesEqual('80 00 00 00 00 00 00 00', XdrEncoder::signedBigInteger64(new BigInteger("-9223372036854775808")));
}

public function testUnsignedBigInteger64()
{
// 100
$this->assertBytesEqual('00 00 00 00 00 00 00 64', XdrEncoder::unsignedBigInteger64(new BigInteger("100")));

// 18446744073709551615
$this->assertBytesEqual('ff ff ff ff ff ff ff ff', XdrEncoder::unsignedBigInteger64(new BigInteger("18446744073709551615")));

// MAX_INT
$this->assertBytesEqual('00 00 00 00 ff ff ff ff', XdrEncoder::unsignedBigInteger64(new BigInteger("4294967295")));

// MAX_INT + 1
$this->assertBytesEqual('00 00 00 01 00 00 00 00', XdrEncoder::unsignedBigInteger64(new BigInteger("4294967296")));

// max positive signed int64
$this->assertBytesEqual('7f ff ff ff ff ff ff ff', XdrEncoder::unsignedBigInteger64(new BigInteger("9223372036854775807")));
}

public function testOpaqueVariable()
{
// Test padding is applied when characters are not a multiple of 4
Expand Down
25 changes: 25 additions & 0 deletions tests/Unit/XdrModel/Operation/BumpSequenceOpTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php


namespace ZuluCrypto\StellarSdk\Test\Unit\XdrModel\Operation;


use phpseclib\Math\BigInteger;
use PHPUnit\Framework\TestCase;
use ZuluCrypto\StellarSdk\Xdr\XdrBuffer;
use ZuluCrypto\StellarSdk\XdrModel\Operation\BumpSequenceOp;
use ZuluCrypto\StellarSdk\XdrModel\Operation\Operation;

class BumpSequenceOpTest extends TestCase
{
public function testFromXdr()
{
$source = new BumpSequenceOp(new BigInteger('1234567890'));

/** @var BumpSequenceOp $parsed */
$parsed = Operation::fromXdr(new XdrBuffer($source->toXdr()));

$this->assertTrue($parsed instanceof BumpSequenceOp);
$this->assertEquals($source->getBumpTo()->toString(), $parsed->getBumpTo()->toString());
}
}
9 changes: 8 additions & 1 deletion tests/Util/HardwareWalletIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,14 @@ public function __construct($name = null, array $data = [], $dataName = '')

// GDRXE2BQUC3AZNPVFSCEZ76NJ3WWL25FYFK6RGZGIEKWE4SOOHSUJUJ6
// SBGWSG6BTNCKCOB3DIFBGCVMUPQFYPA2G4O34RMTB343OYPXU5DJDVMN
$this->mnemonic = 'illness spike retreat truth genius clock brain pass fit cave bargain toe';
//$this->mnemonic = 'illness spike retreat truth genius clock brain pass fit cave bargain toe';

// Mnemonic to match trezor-python test suite
// GAK5MSF74TJW6GLM7NLTL76YZJKM2S4CGP3UH4REJHPHZ4YBZW2GSBPW
// SDE2YU4V2IYSJIUH7MONDYZTSSLDXV5QDEGUUOLCU4TK7CZWTAXZ5CEG
$this->mnemonic = 'alcohol woman abuse must during monitor noble actual mixed trade anger aisle';


$this->privateKeySigner = new PrivateKeySigner(Keypair::newFromMnemonic($this->mnemonic));
}

Expand Down

0 comments on commit 1568ea3

Please sign in to comment.