Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: alternative withdrawal address #4606

Merged
merged 22 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .github/workflows/beekeeper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ jobs:
- name: Test staking
id: stake
run: timeout ${TIMEOUT} beekeeper check --cluster-name local-dns --checks ci-stake
- name: Test withdraw
id: withdraw
run: timeout ${TIMEOUT} bash -c 'until beekeeper check --cluster-name local-dns --checks ci-withdraw; do echo "waiting for withdraw..."; sleep .3; done'
- name: Test redundancy
id: redundancy
run: timeout ${TIMEOUT} beekeeper check --cluster-name local-dns --checks ci-redundancy
Expand Down
130 changes: 66 additions & 64 deletions cmd/bee/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,70 +22,71 @@ import (
)

const (
optionNameDataDir = "data-dir"
optionNameCacheCapacity = "cache-capacity"
optionNameDBOpenFilesLimit = "db-open-files-limit"
optionNameDBBlockCacheCapacity = "db-block-cache-capacity"
optionNameDBWriteBufferSize = "db-write-buffer-size"
optionNameDBDisableSeeksCompaction = "db-disable-seeks-compaction"
optionNamePassword = "password"
optionNamePasswordFile = "password-file"
optionNameAPIAddr = "api-addr"
optionNameP2PAddr = "p2p-addr"
optionNameNATAddr = "nat-addr"
optionNameP2PWSEnable = "p2p-ws-enable"
optionNameDebugAPIEnable = "debug-api-enable"
optionNameDebugAPIAddr = "debug-api-addr"
optionNameBootnodes = "bootnode"
optionNameNetworkID = "network-id"
optionWelcomeMessage = "welcome-message"
optionCORSAllowedOrigins = "cors-allowed-origins"
optionNameTracingEnabled = "tracing-enable"
optionNameTracingEndpoint = "tracing-endpoint"
optionNameTracingHost = "tracing-host"
optionNameTracingPort = "tracing-port"
optionNameTracingServiceName = "tracing-service-name"
optionNameVerbosity = "verbosity"
optionNamePaymentThreshold = "payment-threshold"
optionNamePaymentTolerance = "payment-tolerance-percent"
optionNamePaymentEarly = "payment-early-percent"
optionNameResolverEndpoints = "resolver-options"
optionNameBootnodeMode = "bootnode-mode"
optionNameClefSignerEnable = "clef-signer-enable"
optionNameClefSignerEndpoint = "clef-signer-endpoint"
optionNameClefSignerEthereumAddress = "clef-signer-ethereum-address"
optionNameSwapEndpoint = "swap-endpoint" // deprecated: use rpc endpoint instead
optionNameBlockchainRpcEndpoint = "blockchain-rpc-endpoint"
optionNameSwapFactoryAddress = "swap-factory-address"
optionNameSwapInitialDeposit = "swap-initial-deposit"
optionNameSwapEnable = "swap-enable"
optionNameChequebookEnable = "chequebook-enable"
optionNameSwapDeploymentGasPrice = "swap-deployment-gas-price"
optionNameFullNode = "full-node"
optionNamePostageContractAddress = "postage-stamp-address"
optionNamePostageContractStartBlock = "postage-stamp-start-block"
optionNamePriceOracleAddress = "price-oracle-address"
optionNameRedistributionAddress = "redistribution-address"
optionNameStakingAddress = "staking-address"
optionNameBlockTime = "block-time"
optionWarmUpTime = "warmup-time"
optionNameMainNet = "mainnet"
optionNameRetrievalCaching = "cache-retrieval"
optionNameDevReserveCapacity = "dev-reserve-capacity"
optionNameResync = "resync"
optionNamePProfBlock = "pprof-profile"
optionNamePProfMutex = "pprof-mutex"
optionNameStaticNodes = "static-nodes"
optionNameAllowPrivateCIDRs = "allow-private-cidrs"
optionNameSleepAfter = "sleep-after"
optionNameRestrictedAPI = "restricted"
optionNameTokenEncryptionKey = "token-encryption-key"
optionNameAdminPasswordHash = "admin-password"
optionNameUsePostageSnapshot = "use-postage-snapshot"
optionNameStorageIncentivesEnable = "storage-incentives-enable"
optionNameStateStoreCacheCapacity = "statestore-cache-capacity"
optionNameTargetNeighborhood = "target-neighborhood"
optionNameNeighborhoodSuggester = "neighborhood-suggester"
optionNameDataDir = "data-dir"
optionNameCacheCapacity = "cache-capacity"
optionNameDBOpenFilesLimit = "db-open-files-limit"
optionNameDBBlockCacheCapacity = "db-block-cache-capacity"
optionNameDBWriteBufferSize = "db-write-buffer-size"
optionNameDBDisableSeeksCompaction = "db-disable-seeks-compaction"
optionNamePassword = "password"
optionNamePasswordFile = "password-file"
optionNameAPIAddr = "api-addr"
optionNameP2PAddr = "p2p-addr"
optionNameNATAddr = "nat-addr"
optionNameP2PWSEnable = "p2p-ws-enable"
optionNameDebugAPIEnable = "debug-api-enable"
optionNameDebugAPIAddr = "debug-api-addr"
optionNameBootnodes = "bootnode"
optionNameNetworkID = "network-id"
optionWelcomeMessage = "welcome-message"
optionCORSAllowedOrigins = "cors-allowed-origins"
optionNameTracingEnabled = "tracing-enable"
optionNameTracingEndpoint = "tracing-endpoint"
optionNameTracingHost = "tracing-host"
optionNameTracingPort = "tracing-port"
optionNameTracingServiceName = "tracing-service-name"
optionNameVerbosity = "verbosity"
optionNamePaymentThreshold = "payment-threshold"
optionNamePaymentTolerance = "payment-tolerance-percent"
optionNamePaymentEarly = "payment-early-percent"
optionNameResolverEndpoints = "resolver-options"
optionNameBootnodeMode = "bootnode-mode"
optionNameClefSignerEnable = "clef-signer-enable"
optionNameClefSignerEndpoint = "clef-signer-endpoint"
optionNameClefSignerEthereumAddress = "clef-signer-ethereum-address"
optionNameSwapEndpoint = "swap-endpoint" // deprecated: use rpc endpoint instead
optionNameBlockchainRpcEndpoint = "blockchain-rpc-endpoint"
optionNameSwapFactoryAddress = "swap-factory-address"
optionNameSwapInitialDeposit = "swap-initial-deposit"
optionNameSwapEnable = "swap-enable"
optionNameChequebookEnable = "chequebook-enable"
optionNameSwapDeploymentGasPrice = "swap-deployment-gas-price"
optionNameFullNode = "full-node"
optionNamePostageContractAddress = "postage-stamp-address"
optionNamePostageContractStartBlock = "postage-stamp-start-block"
optionNamePriceOracleAddress = "price-oracle-address"
optionNameRedistributionAddress = "redistribution-address"
optionNameStakingAddress = "staking-address"
optionNameBlockTime = "block-time"
optionWarmUpTime = "warmup-time"
optionNameMainNet = "mainnet"
optionNameRetrievalCaching = "cache-retrieval"
optionNameDevReserveCapacity = "dev-reserve-capacity"
optionNameResync = "resync"
optionNamePProfBlock = "pprof-profile"
optionNamePProfMutex = "pprof-mutex"
optionNameStaticNodes = "static-nodes"
optionNameAllowPrivateCIDRs = "allow-private-cidrs"
optionNameSleepAfter = "sleep-after"
optionNameRestrictedAPI = "restricted"
optionNameTokenEncryptionKey = "token-encryption-key"
optionNameAdminPasswordHash = "admin-password"
optionNameUsePostageSnapshot = "use-postage-snapshot"
optionNameStorageIncentivesEnable = "storage-incentives-enable"
optionNameStateStoreCacheCapacity = "statestore-cache-capacity"
optionNameTargetNeighborhood = "target-neighborhood"
optionNameNeighborhoodSuggester = "neighborhood-suggester"
optionNameWhitelistedWithdrawalAddress = "withdrawal-addresses-whitelist"
)

// nolint:gochecknoinits
Expand Down Expand Up @@ -304,6 +305,7 @@ func (c *command) setAllFlags(cmd *cobra.Command) {
cmd.Flags().Uint64(optionNameStateStoreCacheCapacity, 100_000, "lru memory caching capacity in number of statestore entries")
cmd.Flags().String(optionNameTargetNeighborhood, "", "neighborhood to target in binary format (ex: 111111001) for mining the initial overlay")
cmd.Flags().String(optionNameNeighborhoodSuggester, "https://api.swarmscan.io/v1/network/neighborhoods/suggestion", "suggester for target neighborhood")
cmd.Flags().StringSlice(optionNameWhitelistedWithdrawalAddress, []string{}, "withdrawal target addresses")
}

func newLogger(cmd *cobra.Command, verbosity string) (log.Logger, error) {
Expand Down
1 change: 1 addition & 0 deletions cmd/bee/cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ func buildBeeNode(ctx context.Context, c *command, cmd *cobra.Command, logger lo
StatestoreCacheCapacity: c.config.GetUint64(optionNameStateStoreCacheCapacity),
TargetNeighborhood: c.config.GetString(optionNameTargetNeighborhood),
NeighborhoodSuggester: neighborhoodSuggester,
WhitelistedWithdrawalAddress: c.config.GetStringSlice(optionNameWhitelistedWithdrawalAddress),
})

return b, err
Expand Down
43 changes: 43 additions & 0 deletions openapi/SwarmDebug.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,41 @@ paths:
$ref: "SwarmCommon.yaml#/components/responses/500"
default:
description: Default response
"/wallet/withdraw/{coin}":
post:
summary: Allows withdrawals of BZZ or xDAI to provided (whitelisted) address
tags:
- Wallet
parameters:
- in: query
name: amount
required: true
schema:
$ref: "#/components/schemas/BigInt"
- in: query
name: address
required: true
schema:
$ref: "#/components/schemas/EthereumAddress"
- in: path
name: coin
required: true
schema:
$ref: "#/components/schemas/SwarmAddress"
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/WalletTxResponse'
description: OK
"400":
$ref: "SwarmCommon.yaml#/components/responses/400"
description: Amount greater than ballance or coin is other than BZZ/xDAI
"500":
$ref: "SwarmCommon.yaml#/components/responses/500"
default:
description: Default response

"/transactions":
get:
Expand Down Expand Up @@ -1133,3 +1168,11 @@ paths:
$ref: "SwarmCommon.yaml#/components/responses/400"
default:
description: Default response.

components:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are so these components copied here from SwarmCommon.yaml?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accidental copypaste, reverted

schemas:
WalletTxResponse:
type: object
properties:
transactionHash:
$ref: "#/components/schemas/TransactionHash"
7 changes: 7 additions & 0 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ type Service struct {
erc20Service erc20.Service
chainID int64

whitelistedWithdrawalAddress []common.Address

preMapHooks map[string]func(v string) (string, error)
validate *validator.Validate

Expand Down Expand Up @@ -254,6 +256,7 @@ type ExtraOptions struct {
func New(
publicKey, pssPublicKey ecdsa.PublicKey,
ethereumAddress common.Address,
whitelistedWithdrawalAddress []string,
logger log.Logger,
transaction transaction.Service,
batchStore postage.Storer,
Expand Down Expand Up @@ -303,6 +306,10 @@ func New(
})
s.stamperStore = stamperStore

for _, v := range whitelistedWithdrawalAddress {
s.whitelistedWithdrawalAddress = append(s.whitelistedWithdrawalAddress, common.HexToAddress(v))
}

return s
}

Expand Down
5 changes: 3 additions & 2 deletions pkg/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ type testServerOptions struct {
RedistributionAgent *storageincentives.Agent
NodeStatus *status.Service
PinIntegrity api.PinIntegrity
WhitelistedAddr string
}

func newTestServer(t *testing.T, o testServerOptions) (*http.Client, *websocket.Conn, string, *chanStorer) {
Expand Down Expand Up @@ -210,7 +211,7 @@ func newTestServer(t *testing.T, o testServerOptions) (*http.Client, *websocket.
o.BeeMode = api.FullMode
}

s := api.New(o.PublicKey, o.PSSPublicKey, o.EthereumAddress, o.Logger, transaction, o.BatchStore, o.BeeMode, true, true, backend, o.CORSAllowedOrigins, inmemstore.New())
s := api.New(o.PublicKey, o.PSSPublicKey, o.EthereumAddress, []string{o.WhitelistedAddr}, o.Logger, transaction, o.BatchStore, o.BeeMode, true, true, backend, o.CORSAllowedOrigins, inmemstore.New())
testutil.CleanupCloser(t, s)

s.SetP2P(o.P2P)
Expand Down Expand Up @@ -395,7 +396,7 @@ func TestParseName(t *testing.T) {
pk, _ := crypto.GenerateSecp256k1Key()
signer := crypto.NewDefaultSigner(pk)

s := api.New(pk.PublicKey, pk.PublicKey, common.Address{}, log, nil, nil, 1, false, false, nil, []string{"*"}, inmemstore.New())
s := api.New(pk.PublicKey, pk.PublicKey, common.Address{}, nil, log, nil, nil, 1, false, false, nil, []string{"*"}, inmemstore.New())
s.Configure(signer, nil, nil, api.Options{}, api.ExtraOptions{Resolver: tC.res}, 1, nil)
s.MountAPI()

Expand Down
1 change: 1 addition & 0 deletions pkg/api/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ type (
PostageStampBucketsResponse = postageStampBucketsResponse
BucketData = bucketData
WalletResponse = walletResponse
WalletTxResponse = walletTxResponse
GetStakeResponse = getStakeResponse
WithdrawAllStakeResponse = withdrawAllStakeResponse
StatusSnapshotResponse = statusSnapshotResponse
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,12 @@ func (s *Service) mountBusinessDebug(restricted bool) {
handle("/wallet", jsonhttp.MethodHandler{
"GET": http.HandlerFunc(s.walletHandler),
})
handle("/wallet/withdraw/{coin}", jsonhttp.MethodHandler{
"POST": web.ChainHandlers(
s.gasConfigMiddleware("wallet withdraw"),
web.FinalHandlerFunc(s.walletWithdrawHandler),
),
})
}
}

Expand Down
Loading
Loading