From 567ed95fc2083bd3c83340f46b003d8446ae3400 Mon Sep 17 00:00:00 2001 From: Quentin Le Sceller Date: Thu, 9 May 2019 13:15:10 -0400 Subject: [PATCH 1/6] Set up CI with Azure Pipelines (#2744) Set up CI with Azure Pipelines --- .ci/install.yml | 21 +++++++++++ .ci/release-jobs | 0 .ci/release.yml | 50 +++++++++++++++++++++++++ .ci/test.yml | 10 +++++ .ci/win.patch | 15 ++++++++ .ci/windows-release.yml | 50 +++++++++++++++++++++++++ azure-pipelines.yml | 83 +++++++++++++++++++++++++++++++++++++++++ store/tests/pmmr.rs | 2 +- 8 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 .ci/install.yml mode change 100755 => 100644 .ci/release-jobs create mode 100644 .ci/release.yml create mode 100644 .ci/test.yml create mode 100644 .ci/win.patch create mode 100644 .ci/windows-release.yml create mode 100644 azure-pipelines.yml diff --git a/.ci/install.yml b/.ci/install.yml new file mode 100644 index 0000000000..29c54b0307 --- /dev/null +++ b/.ci/install.yml @@ -0,0 +1,21 @@ +steps: + - script: | + curl -sSf -o rustup-init.exe https://win.rustup.rs + rustup-init.exe -y + echo "##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin" + git apply .ci/win.patch + choco install -y llvm + displayName: Windows Install Rust + condition: eq( variables['Agent.OS'], 'Windows_NT' ) + - script: | + curl https://sh.rustup.rs -sSf | sh -s -- -y + echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin" + displayName: macOS Install Rust + condition: eq( variables['Agent.OS'], 'Darwin' ) + - script: | + curl https://sh.rustup.rs -sSf | sh -s -- -y + sudo apt-get update -yqq + sudo apt-get install -yqq --no-install-recommends libncursesw5-dev + echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin" + displayName: Linux Install Rust and Dependencies + condition: eq( variables['Agent.OS'], 'Linux' ) \ No newline at end of file diff --git a/.ci/release-jobs b/.ci/release-jobs old mode 100755 new mode 100644 diff --git a/.ci/release.yml b/.ci/release.yml new file mode 100644 index 0000000000..6033f7b426 --- /dev/null +++ b/.ci/release.yml @@ -0,0 +1,50 @@ +steps: + - script: 'cargo test --all' + displayName: Cargo Test All + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + - script: 'cargo build --release' + displayName: Build Release + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + - script: | + MY_TAG="$(Build.SourceBranch)" + MY_TAG=${MY_TAG#refs/tags/} + echo $MY_TAG + echo "##vso[task.setvariable variable=build.my_tag]$MY_TAG" + echo "##vso[task.setvariable variable=build.platform]$PLATFORM" + displayName: "Create my tag variable" + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + - task: CopyFiles@2 + displayName: Copy assets + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + inputs: + sourceFolder: '$(Build.SourcesDirectory)/target/release' + contents: 'grin' + targetFolder: '$(Build.BinariesDirectory)/grin' + - task: ArchiveFiles@2 + displayName: Gather assets + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + inputs: + rootFolderOrFile: '$(Build.BinariesDirectory)/grin' + archiveType: 'tar' + tarCompression: 'gz' + archiveFile: '$(Build.ArtifactStagingDirectory)/grin-$(build.my_tag)-$(build.platform).tar.gz' + - script: | + openssl sha256 $(Build.ArtifactStagingDirectory)/grin-$(build.my_tag)-$(build.platform).tar.gz > $(Build.ArtifactStagingDirectory)/grin-$(build.my_tag)-$(build.platform)-sha256sum.txt + displayName: Create Checksum + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + - task: GithubRelease@0 + displayName: Github release + condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + inputs: + gitHubConnection: 'ignopeverell' + repositoryName: 'mimblewimble/grin' + action: 'edit' + target: '$(build.sourceVersion)' + tagSource: 'manual' + tag: '$(build.my_tag)' + assets: | + $(Build.ArtifactStagingDirectory)/grin-$(build.my_tag)-$(build.platform).tar.gz + $(Build.ArtifactStagingDirectory)/grin-$(build.my_tag)-$(build.platform)-sha256sum.txt + title: '$(build.my_tag)' + assetUploadMode: 'replace' + addChangeLog: true \ No newline at end of file diff --git a/.ci/test.yml b/.ci/test.yml new file mode 100644 index 0000000000..65c9bee2f1 --- /dev/null +++ b/.ci/test.yml @@ -0,0 +1,10 @@ +steps: + - script: 'cargo test --all' + displayName: Windows Cargo Test + condition: and(eq( variables['Agent.OS'], 'Windows_NT' ), eq( variables['CI_JOB'], 'test-all' )) + - script: 'cargo test --all' + displayName: macOS Cargo Test + condition: and(eq( variables['Agent.OS'], 'Darwin' ), eq( variables['CI_JOB'], 'test-all' )) + - script: '.ci/general-jobs' + displayName: Linux Cargo Test + condition: eq( variables['Agent.OS'], 'Linux' ) \ No newline at end of file diff --git a/.ci/win.patch b/.ci/win.patch new file mode 100644 index 0000000000..09d54f28e5 --- /dev/null +++ b/.ci/win.patch @@ -0,0 +1,15 @@ +diff --git a/Cargo.toml b/Cargo.toml +index fc8615b6..5ffbf06f 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -45,8 +45,8 @@ cursive = { version = "0.11.0", default-features = false, features = ["pancurses + [target.'cfg(windows)'.dependencies.pancurses] + version = "0.16.0" + features = ["win32"] +-[target.'cfg(unix)'.dependencies] +-cursive = "0.11.0" ++#[target.'cfg(unix)'.dependencies] ++#cursive = "0.11.0" + + [build-dependencies] + built = "0.3" diff --git a/.ci/windows-release.yml b/.ci/windows-release.yml new file mode 100644 index 0000000000..070c5a7245 --- /dev/null +++ b/.ci/windows-release.yml @@ -0,0 +1,50 @@ +steps: + - script: 'cargo test --all' + displayName: Cargo Test All + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + - script: 'cargo build --release' + displayName: Build Release + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + - script: | + SET MY_TAG=$(Build.SourceBranch) + SET MY_TAG=%MY_TAG:~10% + echo %MY_TAG% + echo %PLATFORM% + echo ##vso[task.setvariable variable=build.my_tag]%MY_TAG% + echo ##vso[task.setvariable variable=build.platform]%PLATFORM% + displayName: "Create my tag variable" + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + - task: CopyFiles@2 + displayName: Copy assets + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + inputs: + sourceFolder: '$(Build.SourcesDirectory)\target\release' + contents: 'grin.exe' + targetFolder: '$(Build.BinariesDirectory)\grin' + - task: ArchiveFiles@2 + displayName: Gather assets + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + inputs: + rootFolderOrFile: '$(Build.BinariesDirectory)\grin' + archiveType: 'zip' + archiveFile: '$(Build.ArtifactStagingDirectory)\grin-$(build.my_tag)-$(build.platform).zip' + - script: | + powershell -Command "get-filehash -algorithm sha256 $(Build.ArtifactStagingDirectory)\grin-$(build.my_tag)-$(build.platform).zip | Format-List |  Out-String | ForEach-Object { $_.Trim() } > $(Build.ArtifactStagingDirectory)\grin-$(build.my_tag)-$(build.platform)-sha256sum.txt" + displayName: Create Checksum + condition: and(succeeded(), contains(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + - task: GithubRelease@0 + displayName: Github release + condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), eq(variables['CI_JOB'], 'release' )) + inputs: + gitHubConnection: 'ignopeverell' + repositoryName: 'mimblewimble/grin' + action: 'edit' + target: '$(build.sourceVersion)' + tagSource: 'manual' + tag: '$(build.my_tag)' + assets: | + $(Build.ArtifactStagingDirectory)\grin-$(build.my_tag)-$(build.platform).zip + $(Build.ArtifactStagingDirectory)\grin-$(build.my_tag)-$(build.platform)-sha256sum.txt + title: '$(build.my_tag)' + assetUploadMode: 'replace' + addChangeLog: true diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000..5c041509a8 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,83 @@ +# Copyright 2019 The Grin Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +trigger: + branches: + include: + - master + - milestone/* + tags: + include: ['*'] + +pr: + branches: + include: ['*'] + +variables: + RUST_BACKTRACE: '1' + RUST_FLAGS: '-C debug-assertions' + +jobs: +- job: linux + pool: + vmImage: ubuntu-16.04 + strategy: + matrix: + servers: + CI_JOB: test + CI_JOB_ARGS: servers + chain/core/keychain: + CI_JOB: test + CI_JOB_ARGS: chain core keychain + pool/p2p/src: + CI_JOB: test + CI_JOB_ARGS: pool p2p src + api/util/store: + CI_JOB: test + CI_JOB_ARGS: api util store + release: + CI_JOB: release + PLATFORM: linux-amd64 + steps: + - template: '.ci/install.yml' + - template: '.ci/test.yml' + - template: '.ci/release.yml' +- job: macos + pool: + vmImage: macos-10.13 + strategy: + matrix: + test: + CI_JOB: test-all + release: + CI_JOB: release + PLATFORM: macos + steps: + - template: '.ci/install.yml' + - template: '.ci/test.yml' + - template: '.ci/release.yml' +- job: windows + pool: + vmImage: vs2017-win2016 + strategy: + matrix: + test: + CI_JOB: test-all + release: + CI_JOB: release + PLATFORM: win-x64 + steps: + - template: '.ci/install.yml' + - template: '.ci/test.yml' + - template: '.ci/windows-release.yml' diff --git a/store/tests/pmmr.rs b/store/tests/pmmr.rs index e3970540ef..e70717c658 100644 --- a/store/tests/pmmr.rs +++ b/store/tests/pmmr.rs @@ -776,7 +776,7 @@ fn cleanup_rewind_files_test() { &data_dir, expected, prefix_to_delete, - seconds_to_delete_after, + seconds_to_delete_after + 1, expected, ); // create some files with the save prefix that are old enough to delete, but will be saved because they don't start From 998824ecf3e0d8a53c26b93060cc8bba4f51a65d Mon Sep 17 00:00:00 2001 From: Quentin Le Sceller Date: Thu, 9 May 2019 13:54:24 -0400 Subject: [PATCH 2/6] Add Azure-pipeline badge (#2818) * Add Azure-pipeline badge * Fix formatting --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0e1efcf73..560d9482ef 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://img.shields.io/travis/mimblewimble/grin/master.svg)](https://travis-ci.org/mimblewimble/grin) +[![Build Status](https://dev.azure.com/mimblewimble/grin/_apis/build/status/mimblewimble.grin?branchName=master)](https://dev.azure.com/mimblewimble/grin/_build/latest?definitionId=1&branchName=master) [![Coverage Status](https://img.shields.io/codecov/c/github/mimblewimble/grin/master.svg)](https://codecov.io/gh/mimblewimble/grin) [![Chat](https://img.shields.io/gitter/room/grin_community/Lobby.svg)](https://gitter.im/grin_community/Lobby) [![Support](https://img.shields.io/badge/support-on%20gitter-brightgreen.svg)](https://gitter.im/grin_community/support) From 9ac4143bc9ac313161d706db2530a072c90eb5f0 Mon Sep 17 00:00:00 2001 From: Daogang Tang Date: Mon, 13 May 2019 23:10:31 +0800 Subject: [PATCH 3/6] fix: try to fix issue #2585 by adding block cleanup from db directly. (#2815) * fix: try to fix issue #2585 by adding block cleanup from db directly. Signed-off-by: Mike Tang * use another effective algorithm to do old block and short-lived block cleaup. Signed-off-by: Mike Tang * 1. rename iter_lived_blocks to blocks_iter; 2. comments and iterator calling optimiztions. Signed-off-by: Mike Tang * Fix locking bug when calling is_on_current_chain() in batch.blocks_iter just by removing it. Because "we want to delete block older (i.e. lower height) than tail.height". Signed-off-by: Mike Tang --- chain/src/chain.rs | 34 +++++++--------------------------- chain/src/store.rs | 9 ++++++++- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/chain/src/chain.rs b/chain/src/chain.rs index c0ec8e4331..56b6a52bd2 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -1026,38 +1026,18 @@ impl Chain { } let mut count = 0; - let tail_hash = txhashset.get_header_hash_by_height(head.height - horizon)?; let tail = batch.get_block_header(&tail_hash)?; - let current_hash = txhashset.get_header_hash_by_height(head.height - horizon - 1)?; - let mut current = batch.get_block_header(¤t_hash)?; - - loop { - // Go to the store directly so we can handle NotFoundErr robustly. - match self.store.get_block(¤t.hash()) { - Ok(b) => { - batch.delete_block(&b.hash())?; - count += 1; - } - Err(NotFoundErr(_)) => { - break; - } - Err(e) => { - return Err( - ErrorKind::StoreErr(e, "retrieving block to compact".to_owned()).into(), - ); - } - } - if current.height <= 1 { - break; - } - match batch.get_previous_header(¤t) { - Ok(h) => current = h, - Err(NotFoundErr(_)) => break, - Err(e) => return Err(From::from(e)), + // Remove old blocks (including short lived fork blocks) which height < tail.height + // here b is a block + for (_, b) in batch.blocks_iter()? { + if b.header.height < tail.height { + let _ = batch.delete_block(&b.hash()); + count += 1; } } + batch.save_body_tail(&Tip::from_header(&tail))?; debug!( diff --git a/chain/src/store.rs b/chain/src/store.rs index fe75bbfd5f..58c5b72162 100644 --- a/chain/src/store.rs +++ b/chain/src/store.rs @@ -22,7 +22,7 @@ use crate::types::Tip; use crate::util::secp::pedersen::Commitment; use croaring::Bitmap; use grin_store as store; -use grin_store::{option_to_not_found, to_key, Error}; +use grin_store::{option_to_not_found, to_key, Error, SerIterator}; use std::sync::Arc; const STORE_SUBPATH: &'static str = "chain"; @@ -378,6 +378,13 @@ impl<'a> Batch<'a> { db: self.db.child()?, }) } + + /// An iterator to all block in db + pub fn blocks_iter(&self) -> Result, Error> { + let key = to_key(BLOCK_PREFIX, &mut "".to_string().into_bytes()); + self.db.iter(&key) + } + } /// An iterator on blocks, from latest to earliest, specialized to return From 15b56a97f5e0ebf55af80d47bf33e528454e71b9 Mon Sep 17 00:00:00 2001 From: Daogang Tang Date: Tue, 14 May 2019 05:47:09 +0800 Subject: [PATCH 4/6] docs: fix typo. (#2816) Signed-off-by: Mike Tang --- doc/intro_ZH-CN.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/intro_ZH-CN.md b/doc/intro_ZH-CN.md index b5c3662d28..19c432a0de 100644 --- a/doc/intro_ZH-CN.md +++ b/doc/intro_ZH-CN.md @@ -187,7 +187,7 @@ MimbleWimble区块格式通过引入一个附加概念来构建:核销(_cut- 回顾一下一笔交易的组成: * 一系列交易输入,用来引用并花掉一系列以前的交易输出 -* 一些列新的交易输出(Pedersen commitments) +* 一系列新的交易输出(Pedersen commitments) * 一个交易核,包含: * kernel excess,用来确保等式平衡 * 交易签名(采用kernel excess作为签名公钥) @@ -305,4 +305,4 @@ MimbleWimble区块格式通过引入一个附加概念来构建:核销(_cut- ## 结论 在本文中,我们介绍了基于MimbleWimble区块链的基本原则。 通过使用椭圆曲线密码的附加属性,我们能够构建完全不透明但仍可以正确验证的交易。 -通过将这些属性,我们可以消除大量区块链数据,从而实现新对等点的大规模部署和快速同步。 +通过应用这些属性,我们可以消除大量区块链数据,从而实现新对等点的大规模部署和快速同步。 From 59db5e3bd18d60bd87656dff109a7a56af2e203f Mon Sep 17 00:00:00 2001 From: Quentin Le Sceller Date: Mon, 13 May 2019 18:03:47 -0400 Subject: [PATCH 5/6] Evict transaction from transaction pool (#2797) * Evict transaction from transaction pool * Remove Result from evict function --- pool/src/pool.rs | 2 +- pool/src/transaction_pool.rs | 44 +++++++++++++++++++++++++++++++----- pool/src/types.rs | 2 +- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/pool/src/pool.rs b/pool/src/pool.rs index e21b147023..036c4eff36 100644 --- a/pool/src/pool.rs +++ b/pool/src/pool.rs @@ -310,7 +310,7 @@ impl Pool { /// containing the tx it depends on. /// Sorting the buckets by fee_to_weight will therefore preserve dependency ordering, /// maximizing both cut-through and overall fees. - fn bucket_transactions(&self, weighting: Weighting) -> Vec { + pub fn bucket_transactions(&self, weighting: Weighting) -> Vec { let mut tx_buckets: Vec = Vec::new(); let mut output_commits = HashMap::new(); let mut rejected = HashSet::new(); diff --git a/pool/src/transaction_pool.rs b/pool/src/transaction_pool.rs index f0e0d81de4..3d92aa1da7 100644 --- a/pool/src/transaction_pool.rs +++ b/pool/src/transaction_pool.rs @@ -138,7 +138,13 @@ impl TransactionPool { } // Do we have the capacity to accept this transaction? - self.is_acceptable(&tx, stem)?; + let acceptability = self.is_acceptable(&tx, stem); + let mut evict = false; + if !stem && acceptability.as_ref().err() == Some(&PoolError::OverCapacity) { + evict = true; + } else if acceptability.is_err() { + return acceptability; + } // Make sure the transaction is valid before anything else. // Validate tx accounting for max tx weight. @@ -171,9 +177,36 @@ impl TransactionPool { self.adapter.tx_accepted(&entry.tx); } + // Transaction passed all the checks but we have to make space for it + if evict { + self.evict_from_txpool(); + } + Ok(()) } + // Remove the last transaction from the flattened bucket transactions. + // No other tx depends on it, it has low fee_to_weight and is unlikely to participate in any cut-through. + pub fn evict_from_txpool(&mut self) { + // Get bucket transactions + let bucket_transactions = self.txpool.bucket_transactions(Weighting::NoLimit); + + // Get last transaction and remove it + match bucket_transactions.last() { + Some(evictable_transaction) => { + // Remove transaction + self.txpool.entries = self + .txpool + .entries + .iter() + .filter(|x| x.tx != *evictable_transaction) + .map(|x| x.clone()) + .collect::>(); + } + None => (), + } + } + // Old txs will "age out" after 30 mins. pub fn truncate_reorg_cache(&mut self, cutoff: DateTime) { let mut cache = self.reorg_cache.write(); @@ -245,11 +278,10 @@ impl TransactionPool { } // Check that the stempool can accept this transaction - if stem { - if self.stempool.size() > self.config.max_stempool_size { - // TODO evict old/large transactions instead - return Err(PoolError::OverCapacity); - } + if stem && self.stempool.size() > self.config.max_stempool_size { + return Err(PoolError::OverCapacity); + } else if self.total_size() > self.config.max_pool_size { + return Err(PoolError::OverCapacity); } // for a basic transaction (1 input, 2 outputs) - diff --git a/pool/src/types.rs b/pool/src/types.rs index 20397a514e..3faee7e659 100644 --- a/pool/src/types.rs +++ b/pool/src/types.rs @@ -162,7 +162,7 @@ pub struct TxSource { } /// Possible errors when interacting with the transaction pool. -#[derive(Debug, Fail)] +#[derive(Debug, Fail, PartialEq)] pub enum PoolError { /// An invalid pool entry caused by underlying tx validation error #[fail(display = "Invalid Tx {}", _0)] From 4ba7b0a46adfcf91e07e9d356d5e84328bc25c06 Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Mon, 13 May 2019 23:04:14 +0100 Subject: [PATCH 6/6] make sure we use BigEndian when reading numbers via StreamingReader (#2821) --- core/src/ser.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/ser.rs b/core/src/ser.rs index b5116c22d3..1cc50a8926 100644 --- a/core/src/ser.rs +++ b/core/src/ser.rs @@ -393,32 +393,32 @@ impl<'a> StreamingReader<'a> { impl<'a> Reader for StreamingReader<'a> { fn read_u8(&mut self) -> Result { let buf = self.read_fixed_bytes(1)?; - deserialize(&mut &buf[..]) + Ok(buf[0]) } fn read_u16(&mut self) -> Result { let buf = self.read_fixed_bytes(2)?; - deserialize(&mut &buf[..]) + Ok(BigEndian::read_u16(&buf[..])) } fn read_u32(&mut self) -> Result { let buf = self.read_fixed_bytes(4)?; - deserialize(&mut &buf[..]) + Ok(BigEndian::read_u32(&buf[..])) } fn read_i32(&mut self) -> Result { let buf = self.read_fixed_bytes(4)?; - deserialize(&mut &buf[..]) + Ok(BigEndian::read_i32(&buf[..])) } fn read_u64(&mut self) -> Result { let buf = self.read_fixed_bytes(8)?; - deserialize(&mut &buf[..]) + Ok(BigEndian::read_u64(&buf[..])) } fn read_i64(&mut self) -> Result { let buf = self.read_fixed_bytes(8)?; - deserialize(&mut &buf[..]) + Ok(BigEndian::read_i64(&buf[..])) } /// Read a variable size vector from the underlying stream. Expects a usize