Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
51fdcde
view of address
Pedrozo Oct 28, 2024
7c462b6
view of hash
Pedrozo Oct 29, 2024
384d1ec
view of signature
Pedrozo Oct 30, 2024
4a50279
views modifications
Pedrozo Nov 6, 2024
2b34191
missing docs added
Pedrozo Nov 7, 2024
609758d
merging multiple changes, unfinished work DO NOT MERGE
Pedrozo Sep 29, 2024
d20a725
initial evm executor
Pedrozo Sep 30, 2024
b5b88aa
simplecontract and evm working
Pedrozo Oct 9, 2024
2f4a890
making compilable again
Pedrozo Nov 11, 2024
8b24d42
a lot of things, a lot
Pedrozo Dec 18, 2024
4c50bcf
cursed bug fixed
Pedrozo Dec 19, 2024
af87fe3
more bugs fixed
Pedrozo Dec 19, 2024
ae2be6f
call tracer unfinished (not compilable)
Pedrozo Dec 21, 2024
de6d72a
call tracer tests fixed
Pedrozo Dec 26, 2024
ddaff63
call tracer decoupled
Pedrozo Dec 26, 2024
a6e3ce8
call tracer UB fixed
Pedrozo Dec 27, 2024
0fba68b
precompiled contract added and errors fixed
Pedrozo Jan 6, 2025
ecc20f4
many improvements and fixes related to gas
Pedrozo Jan 8, 2025
f823be8
native wrapper tests fixed
Pedrozo Jan 9, 2025
79b4f6b
fixed accounts behavior when not previously populated, and added prop…
Pedrozo Jan 13, 2025
155fed9
added missing checkpoint commit
Pedrozo Jan 13, 2025
cac0ba8
message dispatcher reorganized
Pedrozo Jan 13, 2025
ce70541
out of gas error fixed
Pedrozo Jan 14, 2025
511371b
simplified call tracer
Pedrozo Jan 14, 2025
054306d
tx additional data added back
Pedrozo Jan 14, 2025
6492dfc
merging development (not compiling)
Pedrozo Jan 15, 2025
8b93a03
fixing merging errors
Pedrozo Jan 15, 2025
3e1c265
removing unused files
Pedrozo Jan 15, 2025
929debd
small style and warnings adjustments
Pedrozo Jan 15, 2025
78a3c4c
fixing failing unit test
Pedrozo Jan 15, 2025
6d3b86d
removed unused stuff
Pedrozo Jan 15, 2025
bdf354c
messages directory removed
Pedrozo Jan 15, 2025
88cbb72
fixed include names
Pedrozo Jan 15, 2025
075aa72
removed unused file
Pedrozo Jan 15, 2025
0a4abbd
added missing include on bytes.h
Pedrozo Jan 16, 2025
da24d43
implementing pull request review comments
Pedrozo Jan 16, 2025
2d226a8
fixing error messages, implementing uint256_t parsing, and fixing UB …
Pedrozo Jan 20, 2025
d8b68dd
15% increase in gas estimation workaround
Pedrozo Jan 20, 2025
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
30 changes: 30 additions & 0 deletions src/bytes/cast.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef BDK_BYTES_CAST_H
#define BDK_BYTES_CAST_H

#include <algorithm>
#include "range.h"

namespace bytes {

/**
* Casts a range of bytes from one type to another.
*
* @param src the input bytes to be cast
* @param dest the destiny bytes container
* @return the destiny bytes container
* @throws invalid argument exception on size incompatibility
*/
template<Range R>
constexpr R cast(const Range auto& src, R dest = R()) {
if (std::ranges::size(src) != std::ranges::size(dest)) {
throw std::invalid_argument("incompatible sizes for casting");
}

std::ranges::copy(src, std::ranges::begin(dest));

return dest;
}

} // namespace bytes

#endif // BDK_BYTES_CAST_H
52 changes: 52 additions & 0 deletions src/bytes/hex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#ifndef BDK_BYTES_HEX_H
#define BDK_BYTES_HEX_H

#include <string_view>
#include <stdexcept>
#include "range.h"
#include "initializer.h"
#include "utils/hex.h"

namespace bytes {

/**
* Creates a sized initializer from a hex representation. The initializer will
* fill the container data with by converting the hexadecimal representation
* into binary data.
* @param str the hex string
* @return the sized initializer
*/
constexpr SizedInitializer auto hex(std::string_view str) {
if (str.size() >= 2 && str.starts_with("0x")) {
str = str.substr(2);
}

if (str.size() % 2) {
throw std::invalid_argument("the length of hex string is required to be even number");
}

return makeInitializer(str.size() / 2, [str] (Byte* dest) {
const auto value = [] (char c) -> Byte {
if (c >= '0' && c <= '9')
return c - '0';
else if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
else if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
else
throw std::invalid_argument("character '" + std::to_string(c) + "' is invalid in hex string");
};

auto it = str.begin();

while (it != str.end()) {
const Byte l = value(*it++);
const Byte r = value(*it++);
*dest++ = (l << 4) | r;
}
});
}

} // namespace bytes

#endif // BDK_BYTES_HEX_H
1 change: 1 addition & 0 deletions src/bytes/initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ See the LICENSE.txt file in the project root for more information.
#ifndef BYTES_INITIALIZER_H
#define BYTES_INITIALIZER_H

#include <functional>
#include "view.h" // range.h -> ranges -> concepts

/// Namespace for bytes-related functionalities.
Expand Down
68 changes: 36 additions & 32 deletions src/bytes/join.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,36 @@ See the LICENSE.txt file in the project root for more information.
#include "initializer.h" // view.h -> range.h

namespace bytes {
namespace detail {
std::size_t joinedSize(const SizedInitializer auto& arg) {
return arg.size();
}

std::size_t joinedSize(const DataRange auto& arg) {
return std::ranges::size(arg);
}

std::size_t joinedSize(const auto& arg, const auto&... args) {
return joinedSize(arg) + joinedSize(args...);
}

Byte* joinImpl(Byte *dest, const SizedInitializer auto& init) {
init.to(dest);
return dest + init.size();
}

Byte* joinImpl(Byte *dest, const DataRange auto& range) {
std::memcpy(dest, std::ranges::data(range), std::ranges::size(range));
return dest + std::ranges::size(range);
}

Byte* joinImpl(Byte *dest, const auto& arg, const auto&... args) {
return joinImpl(joinImpl(dest, arg), args...);
}
} // namespace detail

namespace detail {

std::size_t joinedSize(const SizedInitializer auto& arg) {
return arg.size();
}

std::size_t joinedSize(const DataRange auto& arg) {
return std::ranges::size(arg);
}

std::size_t joinedSize(const auto& arg, const auto&... args) {
return joinedSize(arg) + joinedSize(args...);
}

Byte* joinImpl(Byte *dest, const SizedInitializer auto& init) {
init.to(dest);
return dest + init.size();
}

Byte* joinImpl(Byte *dest, const DataRange auto& range) {
std::memcpy(dest, std::ranges::data(range), std::ranges::size(range));
return dest + std::ranges::size(range);
}

Byte* joinImpl(Byte *dest, const auto& arg, const auto&... args) {
return joinImpl(joinImpl(dest, arg), args...);
}

} // namespace detail

/**
* Join several raw byte strings into one.
Expand All @@ -48,12 +51,13 @@ namespace bytes {
template<typename... Ts> SizedInitializer auto join(Ts&&... args) {
const size_t size = detail::joinedSize(args...);

auto func = [args_ = std::tuple<Ts...>(std::forward<Ts>(args)...)] (Byte *dest) {
std::apply(detail::joinImpl<Ts...>, std::tuple_cat(std::make_tuple(dest), std::tuple<const Ts&...>(args_)));
};
auto func = [args_ = std::tuple<Ts...>(std::forward<Ts>(args)...)] (Byte *dest) {
std::apply(detail::joinImpl<Ts...>, std::tuple_cat(std::make_tuple(dest), std::tuple<const Ts&...>(args_)));
};

return makeInitializer(size, std::move(func));
}

return makeInitializer(size, std::move(func));
}
} // namespace bytes

#endif // BYTES_JOIN_H
40 changes: 40 additions & 0 deletions src/bytes/random.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef BDK_BYTES_RANDOM_H
#define BDK_BYTES_RANDOM_H

#include "range.h"
#include "initializer.h"

#include <openssl/rand.h>

namespace bytes {

/**
* Creates an initializer of random bytes.
* The number of generated bytes exactly matches the size of the target bytes range.
*
* Examples:
* Hash hash = bytes::random(); // generates 32 random bytes
* Address addr = bytes::random(); // generates 20 random bytes
*
* @return a random bytes initializer
*/
constexpr Initializer auto random() {
return makeInitializer([] (Span span) {
::RAND_bytes(span.data(), span.size());
});
}

/**
* Creates an random bytes initializer of the given size.
*
* @return a sized initializer of random bytes
*/
constexpr SizedInitializer auto random(size_t size) {
return makeInitializer(size, [size] (Byte* ptr) {
::RAND_bytes(ptr, size);
});
}

} // namespace bytes

#endif // BDK_BYTES_RANDOM_H
15 changes: 13 additions & 2 deletions src/bytes/range.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,21 @@ See the LICENSE.txt file in the project root for more information.
#define BYTES_RANGE_H

#include <ranges>

using Byte = std::uint8_t;
#include "utils/bytes.h"

namespace bytes {
/**
* Concept of a bytes iterator.
*/
template<typename T>
concept Iterator = std::input_or_output_iterator<T> && std::same_as<std::iter_value_t<T>, Byte>;

/**
* Concept of a bytes contiguous bytes iterator.
*/
template<typename T>
concept DataIterator = Iterator<T> && std::contiguous_iterator<T>;

/**
* The concept of a range of bytes.
*/
Expand Down
17 changes: 4 additions & 13 deletions src/bytes/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@
#define BYTES_VIEW_H

#include "range.h" // ranges -> span
#include "utils/view.h"

namespace bytes {

/// A view over sized contiguous bytes
using View = std::span<const Byte>;

/// A span (i.e. a non-owning array of bytes that allows modification) over sized contiguous bytes
using Span = std::span<Byte>;

/**
Expand All @@ -20,7 +17,7 @@ using Span = std::span<Byte>;
* @return a view object of the bytes
*/
template<BorrowedDataRange R>
constexpr View view(R&& r) { return View(std::forward<R>(r)); }
constexpr View<Bytes> view(R&& r) { return View<Bytes>(std::forward<R>(r)); }

/**
* Creates a span from the given data range. It needs to be Borrowed
Expand All @@ -41,8 +38,8 @@ constexpr Span span(R&& r) { return Span(std::forward<R>(r)); }
* @param str the target string
* @return a bytes view of the string bytes
*/
inline View view(std::string_view str) {
return View(reinterpret_cast<const Byte*>(str.data()), str.size());
inline View<Bytes> view(std::string_view str) {
return View<Bytes>(reinterpret_cast<const Byte*>(str.data()), str.size());
}

/**
Expand All @@ -55,12 +52,6 @@ inline Span span(std::string& str) {
return Span(reinterpret_cast<Byte*>(str.data()), str.size());
}

/// The concept of a type that can be viewed as a sized range of contiguous bytes.
template<typename T>
concept Viewable = requires(const T& a) {
{ view(a) } -> std::convertible_to<View>;
};

} // namespace bytes

#endif // BYTES_VIEW_H
6 changes: 5 additions & 1 deletion src/contract/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ set(CONTRACT_SOURCES
${CMAKE_SOURCE_DIR}/src/contract/contracthost.cpp
${CMAKE_SOURCE_DIR}/src/contract/contractmanager.cpp
${CMAKE_SOURCE_DIR}/src/contract/dynamiccontract.cpp
${CMAKE_SOURCE_DIR}/src/contract/calltracer.cpp
${CMAKE_SOURCE_DIR}/src/contract/trace/call.cpp
${CMAKE_SOURCE_DIR}/src/contract/event.cpp
${CMAKE_SOURCE_DIR}/src/contract/common.cpp
${CMAKE_SOURCE_DIR}/src/contract/executioncontext.cpp
${CMAKE_SOURCE_DIR}/src/contract/evmcontractexecutor.cpp
${CMAKE_SOURCE_DIR}/src/contract/precompiledcontractexecutor.cpp
${CMAKE_SOURCE_DIR}/src/contract/templates/ownable.cpp
${CMAKE_SOURCE_DIR}/src/contract/templates/erc20.cpp
${CMAKE_SOURCE_DIR}/src/contract/templates/erc721.cpp
Expand Down
35 changes: 33 additions & 2 deletions src/contract/abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,48 @@ Bytes ABI::Encoder::encodeInt(const int256_t& num) {
return ret;
}

uint256_t ABI::Decoder::decodeUint(const bytes::View &bytes, uint64_t &index) {
uint256_t ABI::Decoder::decodeUint(const View<Bytes> &bytes, uint64_t &index) {
if (index + 32 > bytes.size()) throw std::length_error("Data too short for uint256");
uint256_t result = UintConv::bytesToUint256(bytes.subspan(index, 32));
index += 32;
return result;
}

int256_t ABI::Decoder::decodeInt(const bytes::View& bytes, uint64_t& index) {
int256_t ABI::Decoder::decodeInt(const View<Bytes>& bytes, uint64_t& index) {
if (index + 32 > bytes.size()) throw std::length_error("Data too short for int256");
int256_t result = IntConv::bytesToInt256(bytes.subspan(index, 32));
index += 32;
return result;
}

Bytes ABI::Encoder::encodeError(std::string_view reason) {
FixedBytes<32> reasonEncoded{};

const size_t count = std::min(reason.size(), reasonEncoded.size());
std::copy_n(reason.begin(), count, reasonEncoded.begin());

const uint256_t size(reason.size());
const FixedBytes<32> sizeEncoded(UintConv::uint256ToBytes(size));

return Utils::makeBytes(bytes::join(
Hex::toBytes("0x08c379a0"),
Hex::toBytes("0x0000000000000000000000000000000000000000000000000000000000000020"),
sizeEncoded,
reasonEncoded
));
}

std::string ABI::Decoder::decodeError(View<Bytes> data) {
static constexpr size_t MAX_STR_SIZE = 32;

if (data.size() != 100) {
throw DynamicException("Encoded revert reason is expected to have exactly 100 bytes");
}

const size_t size = std::min(size_t(UintConv::bytesToUint256(data.subspan(36, 32))), MAX_STR_SIZE);

std::string res;
res.reserve(size);
std::ranges::copy(data.subspan(68, size), std::back_inserter(res));
return res;
}
Loading