Skip to content

Commit

Permalink
Merge pull request #1024 from iotaledger/develop
Browse files Browse the repository at this point in the history
Merge v0.4.1 to master
  • Loading branch information
capossele authored Mar 2, 2021
2 parents 8c05675 + 4813896 commit 03d9f6e
Show file tree
Hide file tree
Showing 42 changed files with 648 additions and 360 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# v0.4.1 - 2021-03-02
* Add orphanage analysis tool
* Add documentation web-api
* Simplify past-cone checks
* Improve message findByID API
* Improve value transactionByID API
* Fix saving markers in message metadata
* Fix issue with ReferenceUnlockBlocks
* Fix Faucet address blacklist
* Fix some visualizer glitches
* **Breaking**: bumps network and database versions

# v0.4.0 - 2021-02-26
* Remove the value Tangle
* Add approval switch
Expand Down
14 changes: 12 additions & 2 deletions client/wallet/wallet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,21 @@ func TestWallet_SendFunds(t *testing.T) {
{
name: "validTransfer",
parameters: []SendFundsOption{
Destination(receiverSeed.Address(0), 1200),
Destination(receiverSeed.Address(0), 1999),
},
validator: func(t *testing.T, tx *ledgerstate.Transaction, err error) {
assert.False(t, tx == nil, "there should be a transaction created")
assert.Nil(t, err)
assert.True(t, ledgerstate.UnlockBlocksValid(ledgerstate.NewOutputs(
ledgerstate.NewSigLockedColoredOutput(ledgerstate.NewColoredBalances(map[ledgerstate.Color]uint64{
ledgerstate.ColorIOTA: 1337,
{3}: 1338,
}), senderSeed.Address(0).Address()).SetID(ledgerstate.NewOutputID(ledgerstate.TransactionID{3}, 0)),
ledgerstate.NewSigLockedColoredOutput(ledgerstate.NewColoredBalances(map[ledgerstate.Color]uint64{
ledgerstate.ColorIOTA: 663,
{4}: 1338,
}), senderSeed.Address(0).Address()).SetID(ledgerstate.NewOutputID(ledgerstate.TransactionID{3}, 0)),
), tx))
},
},

Expand Down Expand Up @@ -109,7 +119,7 @@ func TestWallet_SendFunds(t *testing.T) {

// create our test wallet
wallet := New(
Import(senderSeed, 1, []bitmask.BitMask{}, NewAssetRegistry()),
Import(senderSeed, 2, []bitmask.BitMask{}, NewAssetRegistry()),
GenericConnector(mockedConnector),
)

Expand Down
67 changes: 67 additions & 0 deletions docs/tooling/webAPI_clientLib.md
Original file line number Diff line number Diff line change
@@ -1 +1,68 @@
# WebAPI - clientLib


The web API interface allows to access functionality of the node software via exposed http endpoints.

## How to use the API

The default port to access the web API is set to `8080:8080/tcp` in `docker-compose.yml`, where the first port number is the internal port number within the node software, and the second for the access from an http port. An example where these two would be set to different values, or the external port is not utilized, can be found in the docker-network tool (see also the `docker-compose.yml` file in the docker-network tool folder).

The server instance of the web API is contacted via `webapi.Server()`. Next we need to register a route with a matching handler.

```
webapi.Server().ROUTE(path string, h HandlerFunc)
```
where `ROUTE` will be replaced later in this documentation by `GET` or `POST`. The `HandlerFunc` defines a function to serve HTTP requests that gives access to the Context

```
func HandlerFunc(c Context) error
```
We can then use the Context to send a JSON response to the node:
```
JSON(statuscode int, i interface{}) error
```
An implementation example is shown later for the POST method.

## GET and POST

Two methods are currently used. First, with `GET` we register a new GET route for a handler function. The handler is accessed via the address `path`. The handler for a GET method can set the node to perform certain actions.
```
webapi.Server().GET("path", HandlerFunc)
```
A command can be sent to the node software to the API, e.g. via command prompt:
```
curl "http://127.0.0.1:8080/path?command"
```

$$ . $$

Second, with `POST` we register a new POST route for a handler function. The handler can receive a JSON body input and send specific messages to the tangle.
```
webapi.Server().POST("path", HandlerFunc)
```

For example, the following Handler `broadcastData` sends a data message to the tangle
```
func broadcastData(c echo.Context) error {
var request Request
if err := c.Bind(&request); err != nil {
log.Info(err.Error())
return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
}
msg, err := issuer.IssuePayload(
payload.NewGenericDataPayload(request.Data), messagelayer.Tangle())
if err != nil {
return c.JSON(http.StatusBadRequest, Response{Error: err.Error()})
}
return c.JSON(http.StatusOK, Response{ID: msg.ID().String()})
}
```
As an example the JSON body
```
{
"data":"HelloWor"
}
```
can be sent to `http://127.0.0.1:8080/data`, which will issue a data message containing "HelloWor" (note that in this example the data input is size limited.)

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/golang/protobuf v1.4.3
github.com/golang/snappy v0.0.2 // indirect
github.com/gorilla/websocket v1.4.2
github.com/iotaledger/hive.go v0.0.0-20210224233715-cb935d64415d
github.com/iotaledger/hive.go v0.0.0-20210228213009-bdcfaf0d67c0
github.com/kr/pretty v0.2.1 // indirect
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.3.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,8 @@ github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:q
github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/iotaledger/hive.go v0.0.0-20210224233715-cb935d64415d h1:soR4+LgoHyeanCEQo6zHm604uMjM1La0N/kaScO2bEs=
github.com/iotaledger/hive.go v0.0.0-20210224233715-cb935d64415d/go.mod h1:dFt9vuTF3FdDPx7ve+uSDiNrX2PW2eV8sq7N06jeaFw=
github.com/iotaledger/hive.go v0.0.0-20210228213009-bdcfaf0d67c0 h1:of3/vsKov5UgIgGY0T9RnMKj9aZB/2FWJguyyd/IWOY=
github.com/iotaledger/hive.go v0.0.0-20210228213009-bdcfaf0d67c0/go.mod h1:dFt9vuTF3FdDPx7ve+uSDiNrX2PW2eV8sq7N06jeaFw=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
Expand Down
7 changes: 2 additions & 5 deletions packages/database/prefix.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,12 @@ const (
// PrefixHealth defines the prefix of the health db.
PrefixHealth

// PrefixMessageLayer defines the storage prefix for the message layer.
PrefixMessageLayer
// PrefixTangle defines the storage prefix for the tangle.
PrefixTangle

// PrefixMarkers defines the storage prefix for the markers used to optimize structural checks in the tangle.
PrefixMarkers

// PrefixValueTransfers defines the storage prefix for value transfer.
PrefixValueTransfers

// PrefixLedgerState defines the storage prefix for the ledgerstate package.
PrefixLedgerState
)
4 changes: 4 additions & 0 deletions packages/ledgerstate/branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ func (b BranchID) String() string {
switch b {
case UndefinedBranchID:
return "BranchID(UndefinedBranchID)"
case LazyBookedConflictsBranchID:
return "BranchID(LazyBookedConflictsBranchID)"
case InvalidBranchID:
return "BranchID(InvalidBranchID)"
case MasterBranchID:
return "BranchID(MasterBranchID)"
default:
Expand Down
38 changes: 19 additions & 19 deletions packages/ledgerstate/signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,15 @@ func SignatureFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (signature S

// ED25519Signature represents a Signature created with the ed25519 signature scheme.
type ED25519Signature struct {
publicKey ed25519.PublicKey
signature ed25519.Signature
PublicKey ed25519.PublicKey
Signature ed25519.Signature
}

// NewED25519Signature is the constructor of an ED25519Signature.
func NewED25519Signature(publicKey ed25519.PublicKey, signature ed25519.Signature) *ED25519Signature {
return &ED25519Signature{
publicKey: publicKey,
signature: signature,
PublicKey: publicKey,
Signature: signature,
}
}

Expand Down Expand Up @@ -175,11 +175,11 @@ func ED25519SignatureFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (sign
}

signature = &ED25519Signature{}
if signature.publicKey, err = ed25519.ParsePublicKey(marshalUtil); err != nil {
if signature.PublicKey, err = ed25519.ParsePublicKey(marshalUtil); err != nil {
err = xerrors.Errorf("failed to parse public key (%v): %w", err, cerrors.ErrParseBytesFailed)
return
}
if signature.signature, err = ed25519.ParseSignature(marshalUtil); err != nil {
if signature.Signature, err = ed25519.ParseSignature(marshalUtil); err != nil {
err = xerrors.Errorf("failed to parse signature (%v): %w", err, cerrors.ErrParseBytesFailed)
return
}
Expand All @@ -193,7 +193,7 @@ func (e *ED25519Signature) Type() SignatureType {

// SignatureValid returns true if the Signature signs the given data.
func (e *ED25519Signature) SignatureValid(data []byte) bool {
return e.publicKey.VerifySignature(data, e.signature)
return e.PublicKey.VerifySignature(data, e.Signature)
}

// AddressSignatureValid returns true if the Signature signs the given Address.
Expand All @@ -202,7 +202,7 @@ func (e *ED25519Signature) AddressSignatureValid(address Address, data []byte) b
return false
}

hashedPublicKey := blake2b.Sum256(e.publicKey.Bytes())
hashedPublicKey := blake2b.Sum256(e.PublicKey.Bytes())
if !bytes.Equal(hashedPublicKey[:], address.Digest()) {
return false
}
Expand All @@ -212,7 +212,7 @@ func (e *ED25519Signature) AddressSignatureValid(address Address, data []byte) b

// Bytes returns a marshaled version of the Signature.
func (e *ED25519Signature) Bytes() []byte {
return byteutils.ConcatBytes([]byte{byte(ED25519SignatureType)}, e.publicKey.Bytes(), e.signature.Bytes())
return byteutils.ConcatBytes([]byte{byte(ED25519SignatureType)}, e.PublicKey.Bytes(), e.Signature.Bytes())
}

// Base58 returns a base58 encoded version of the Signature.
Expand All @@ -223,8 +223,8 @@ func (e *ED25519Signature) Base58() string {
// String returns a human readable version of the Signature.
func (e *ED25519Signature) String() string {
return stringify.Struct("ED25519Signature",
stringify.StructField("publicKey", e.publicKey),
stringify.StructField("signature", e.signature),
stringify.StructField("publicKey", e.PublicKey),
stringify.StructField("signature", e.Signature),
)
}

Expand All @@ -237,13 +237,13 @@ var _ Signature = &ED25519Signature{}

// BLSSignature represents a Signature created with the BLS signature scheme.
type BLSSignature struct {
signature bls.SignatureWithPublicKey
Signature bls.SignatureWithPublicKey
}

// NewBLSSignature is the constructor of a BLSSignature.
func NewBLSSignature(signature bls.SignatureWithPublicKey) *BLSSignature {
return &BLSSignature{
signature: signature,
Signature: signature,
}
}

Expand Down Expand Up @@ -288,7 +288,7 @@ func BLSSignatureFromMarshalUtil(marshalUtil *marshalutil.MarshalUtil) (signatur
}

signature = &BLSSignature{}
if signature.signature, err = bls.SignatureWithPublicKeyFromMarshalUtil(marshalUtil); err != nil {
if signature.Signature, err = bls.SignatureWithPublicKeyFromMarshalUtil(marshalUtil); err != nil {
err = xerrors.Errorf("failed to parse SignatureWithPublicKey from MarshalUtil (%v): %w", err, cerrors.ErrParseBytesFailed)
return
}
Expand All @@ -303,7 +303,7 @@ func (b *BLSSignature) Type() SignatureType {

// SignatureValid returns true if the Signature signs the given data.
func (b *BLSSignature) SignatureValid(data []byte) bool {
return b.signature.IsValid(data)
return b.Signature.IsValid(data)
}

// AddressSignatureValid returns true if the Signature signs the given Address.
Expand All @@ -312,7 +312,7 @@ func (b *BLSSignature) AddressSignatureValid(address Address, data []byte) bool
return false
}

hashedPublicKey := blake2b.Sum256(b.signature.PublicKey.Bytes())
hashedPublicKey := blake2b.Sum256(b.Signature.PublicKey.Bytes())
if !bytes.Equal(hashedPublicKey[:], address.Digest()) {
return false
}
Expand All @@ -322,7 +322,7 @@ func (b *BLSSignature) AddressSignatureValid(address Address, data []byte) bool

// Bytes returns a marshaled version of the Signature.
func (b *BLSSignature) Bytes() []byte {
return byteutils.ConcatBytes([]byte{byte(BLSSignatureType)}, b.signature.Bytes())
return byteutils.ConcatBytes([]byte{byte(BLSSignatureType)}, b.Signature.Bytes())
}

// Base58 returns a base58 encoded version of the Signature.
Expand All @@ -333,8 +333,8 @@ func (b *BLSSignature) Base58() string {
// String returns a human readable version of the Signature.
func (b *BLSSignature) String() string {
return stringify.Struct("BLSSignature",
stringify.StructField("publicKey", b.signature.PublicKey),
stringify.StructField("signature", b.signature.Signature),
stringify.StructField("publicKey", b.Signature.PublicKey),
stringify.StructField("signature", b.Signature.Signature),
)
}

Expand Down
10 changes: 10 additions & 0 deletions packages/ledgerstate/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ func (i TransactionID) String() string {
// TransactionIDs represents a collection of TransactionIDs.
type TransactionIDs map[TransactionID]types.Empty

// Clone returns a copy of the collection of TransactionIDs.
func (t TransactionIDs) Clone() (transactionIDs TransactionIDs) {
transactionIDs = make(TransactionIDs)
for transactionID := range t {
transactionIDs[transactionID] = types.Void
}

return
}

// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////

// region Transaction //////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
63 changes: 63 additions & 0 deletions packages/ledgerstate/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,69 @@ import (
"math"
)

// TransactionBalancesValid is an internal utility function that checks if the sum of the balance changes equals to 0.
func TransactionBalancesValid(inputs Outputs, outputs Outputs) (valid bool) {
consumedCoins := make(map[Color]uint64)
for _, input := range inputs {
input.Balances().ForEach(func(color Color, balance uint64) bool {
consumedCoins[color], valid = SafeAddUint64(consumedCoins[color], balance)

return valid
})

if !valid {
return
}
}

recoloredCoins := uint64(0)
for _, output := range outputs {
output.Balances().ForEach(func(color Color, balance uint64) bool {
switch color {
case ColorIOTA:
fallthrough
case ColorMint:
recoloredCoins, valid = SafeAddUint64(recoloredCoins, balance)
default:
consumedCoins[color], valid = SafeSubUint64(consumedCoins[color], balance)
}

return valid
})

if !valid {
return
}
}

unspentCoins := uint64(0)
for _, remainingBalance := range consumedCoins {
if unspentCoins, valid = SafeAddUint64(unspentCoins, remainingBalance); !valid {
return
}
}

return unspentCoins == recoloredCoins
}

// UnlockBlocksValid is an internal utility function that checks if the UnlockBlocks are matching the referenced Inputs.
func UnlockBlocksValid(inputs Outputs, transaction *Transaction) (valid bool) {
unlockBlocks := transaction.UnlockBlocks()
for i, input := range inputs {
currentUnlockBlock := unlockBlocks[i]
if currentUnlockBlock.Type() == ReferenceUnlockBlockType {
currentUnlockBlock = unlockBlocks[unlockBlocks[i].(*ReferenceUnlockBlock).ReferencedIndex()]
}

unlockValid, unlockErr := input.UnlockValid(transaction, currentUnlockBlock)
if !unlockValid || unlockErr != nil {
return false
}
}

return true
}

// SafeAddUint64 adds two uint64 values. It returns the result and a valid flag that indicates whether the addition is
// valid without causing an overflow.
func SafeAddUint64(a uint64, b uint64) (result uint64, valid bool) {
Expand Down
Loading

0 comments on commit 03d9f6e

Please sign in to comment.